From: Yoshito Umaoka Date: Wed, 7 Sep 2011 22:47:55 +0000 (+0000) Subject: ICU-8769 Reverted the previous change because of loading status issue. Move the cache... X-Git-Tag: milestone-59-0-1~4545 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=27b6a943bc291eaec65f327ce6f88fdce9708b5d;p=icu ICU-8769 Reverted the previous change because of loading status issue. Move the cache to ICUResourceBundleReader that actually hold the resource data. Moved pool key bundle initialization to ICUResourceBundle to prevent cached instances modified by other classes. X-SVN-Rev: 30633 --- diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java index f3ecee8081d..722818081cb 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundle.java @@ -825,7 +825,7 @@ public class ICUResourceBundle extends UResourceBundle { if(localeName.indexOf('@')>=0){ localeName = ULocale.getBaseName(localeID); } - String fullName = getFullName(baseName, localeName); + String fullName = ICUResourceBundleReader.getFullName(baseName, localeName); ICUResourceBundle b = (ICUResourceBundle)loadFromCache(root, fullName, defaultLocale); // here we assume that java type resource bundle organization @@ -836,7 +836,7 @@ public class ICUResourceBundle extends UResourceBundle { // com.mycompany.data.MyLocaleElements.res // final String rootLocale = (baseName.indexOf('.')==-1) ? "root" : ""; - final String defaultID = defaultLocale.toString(); + final String defaultID = defaultLocale.getBaseName(); if(localeName.equals("")){ localeName = rootLocale; @@ -905,7 +905,7 @@ public class ICUResourceBundle extends UResourceBundle { obj = (ICUResourceBundle)obj.get(aKey, table, requested); } if (obj == null) { - String fullName = getFullName(getBaseName(), getLocaleID()); + String fullName = ICUResourceBundleReader.getFullName(getBaseName(), getLocaleID()); throw new MissingResourceException( "Can't find resource for bundle " + fullName + ", key " + aKey, this.getClass().getName(), aKey); @@ -915,34 +915,6 @@ public class ICUResourceBundle extends UResourceBundle { return obj; } - private static final String ICU_RESOURCE_SUFFIX = ".res"; - /** - * Gets the full name of the resource with suffix. - */ - public static String getFullName(String baseName, String localeName){ - if(baseName==null || baseName.length()==0){ - if(localeName.length()==0){ - return localeName=ULocale.getDefault().toString(); - } - return localeName+ICU_RESOURCE_SUFFIX; - }else{ - if(baseName.indexOf('.')==-1){ - if(baseName.charAt(baseName.length()-1)!= '/'){ - return baseName+"/"+localeName+ICU_RESOURCE_SUFFIX; - }else{ - return baseName+localeName+ICU_RESOURCE_SUFFIX; - } - }else{ - baseName = baseName.replace('.','/'); - if(localeName.length()==0){ - return baseName+ICU_RESOURCE_SUFFIX; - }else{ - return baseName+"_"+localeName+ICU_RESOURCE_SUFFIX; - } - } - } - } - protected String localeID; protected String baseName; protected ULocale ulocale; @@ -994,74 +966,6 @@ public class ICUResourceBundle extends UResourceBundle { */ public static final int ARRAY16 = 9; - /* - * Bundle cache stuff - */ - - /** - * Place holder in the bundle cache indicating that the requested bundle is not available - */ - private static final ICUResourceBundle NULL_BUNDLE = - new ICUResourceBundle(null, null, null, 0, null) { - public int hashCode() { - return 0; - } - public boolean equals(Object rhs) { - return this == rhs; - } - }; - - /** - * An object storing information required for creating a bundle, used by - * the bundle cache. - */ - private static class BundleCacheData { - ClassLoader root; - String baseName; - String localeID; - - BundleCacheData(ClassLoader root, String baseName, String localeID) { - this.root = root; - this.baseName = baseName; - this.localeID = localeID; - } - - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof BundleCacheData)) { - return false; - } - BundleCacheData data = (BundleCacheData)obj; - return this.root.equals(data.root) && - this.baseName.equals(data.baseName) && - this.localeID.equals(data.localeID); - } - - public int hashCode() { - return root.hashCode() ^ baseName.hashCode() ^ localeID.hashCode(); - } - } - - private static class BundleCache extends SoftCache { - - /* (non-Javadoc) - * @see com.ibm.icu.impl.CacheBase#createInstance(java.lang.Object, java.lang.Object) - */ - @Override - protected ICUResourceBundle createInstance(BundleCacheData key, BundleCacheData data) { - String resolvedName = getFullName(data.baseName, data.localeID); - ICUResourceBundleReader reader = ICUResourceBundleReader.getReader(resolvedName, data.root); - if (reader == null) { - return NULL_BUNDLE; - } - return ICUResourceBundle.getBundle(reader, data.baseName, data.localeID, data.root); - } - } - - private static final BundleCache BUNDLE_CACHE = new BundleCache(); - /** * Create a bundle using a reader. * @param baseName The name for the bundle. @@ -1070,9 +974,12 @@ public class ICUResourceBundle extends UResourceBundle { * @return the new bundle */ public static ICUResourceBundle createBundle(String baseName, String localeID, ClassLoader root) { - BundleCacheData bundleKey = new BundleCacheData(root, baseName, localeID); - ICUResourceBundle b = BUNDLE_CACHE.getInstance(bundleKey, bundleKey); - return b == NULL_BUNDLE ? null : b; + ICUResourceBundleReader reader = ICUResourceBundleReader.getReader(baseName, localeID, root); + if (reader == null) { + // could not open the .res file + return null; + } + return getBundle(reader, baseName, localeID, root); } protected String getLocaleID() { @@ -1147,10 +1054,6 @@ public class ICUResourceBundle extends UResourceBundle { bundle.localeID = localeID; bundle.ulocale = new ULocale(localeID); bundle.loader = loader; - if(bundle.reader.getUsesPoolBundle()) { - bundle.reader.setPoolBundleKeys( - ((ICUResourceBundleImpl)getBundleInstance(baseName, "pool", loader, true)).reader); - } UResourceBundle alias = bundle.handleGetImpl("%%ALIAS", null, bundle, null, null); // handleGet will cache the bundle with no parent set if(alias != null) { return (ICUResourceBundle)UResourceBundle.getBundleInstance(baseName, alias.getString()); diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundleReader.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundleReader.java index 8883afcb336..b230776c35d 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundleReader.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/impl/ICUResourceBundleReader.java @@ -12,6 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; +import com.ibm.icu.util.ULocale; import com.ibm.icu.util.UResourceBundle; import com.ibm.icu.util.VersionInfo; @@ -271,43 +272,102 @@ public final class ICUResourceBundleReader implements ICUBinary.Authenticate { private byte[] resourceBytes; private int resourceBottom; // File offset where the mixed-type resources start. - private ICUResourceBundleReader(InputStream stream, String resolvedName){ + private static ReaderCache CACHE = new ReaderCache(); + private static final ICUResourceBundleReader NULL_READER = new ICUResourceBundleReader(); + + private static class ReaderInfo { + final String baseName; + final String localeID; + final ClassLoader loader; + + ReaderInfo(String baseName, String localeID, ClassLoader loader) { + this.baseName = (baseName == null) ? "" : baseName; + this.localeID = (localeID == null) ? "" : localeID; + this.loader = loader; + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ReaderInfo)) { + return false; + } + ReaderInfo info = (ReaderInfo)obj; + return this.baseName.equals(info.baseName) + && this.localeID.equals(info.localeID) + && this.loader.equals(info.loader); + } + + public int hashCode() { + return baseName.hashCode() ^ localeID.hashCode() ^ loader.hashCode(); + } + } + + private static class ReaderCache extends SoftCache { + /* (non-Javadoc) + * @see com.ibm.icu.impl.CacheBase#createInstance(java.lang.Object, java.lang.Object) + */ + @Override + protected ICUResourceBundleReader createInstance(ReaderInfo key, ReaderInfo data) { + String fullName = ICUResourceBundleReader.getFullName(data.baseName, data.localeID); + InputStream stream = ICUData.getStream(data.loader, fullName); + if (stream == null) { + return NULL_READER; + } + return new ICUResourceBundleReader(stream, data.baseName, data.localeID, data.loader); + } + } + + /* + * Sole constructor, just used for NULL_READER + */ + private ICUResourceBundleReader() { + } + + private ICUResourceBundleReader(InputStream stream, String baseName, String localeID, ClassLoader loader) { BufferedInputStream bs = new BufferedInputStream(stream); - try{ - if(DEBUG) System.out.println("The InputStream class is: " + stream.getClass().getName()); - if(DEBUG) System.out.println("The BufferedInputStream class is: " + bs.getClass().getName()); - if(DEBUG) System.out.println("The bytes avialable in stream before reading the header: " + bs.available()); - - dataVersion = ICUBinary.readHeader(bs,DATA_FORMAT_ID,this); - - if(DEBUG) System.out.println("The bytes available in stream after reading the header: " + bs.available()); - + try { + if (DEBUG) { + System.out.println("The InputStream class is: " + stream.getClass().getName()); + System.out.println("The BufferedInputStream class is: " + bs.getClass().getName()); + System.out.println("The bytes avialable in stream before reading the header: " + bs.available()); + } + + dataVersion = ICUBinary.readHeader(bs, DATA_FORMAT_ID, this); + + if (DEBUG) System.out.println("The bytes available in stream after reading the header: " + bs.available()); + readData(bs); stream.close(); - }catch(IOException ex){ - throw new RuntimeException("Data file "+ resolvedName+ " is corrupt - " + ex.getMessage()); + + } catch (IOException ex) { + String fullName = ICUResourceBundleReader.getFullName(baseName, localeID); + throw new RuntimeException("Data file " + fullName + " is corrupt - " + ex.getMessage()); + } + + // set pool bundle keys if necessary + if (usesPoolBundle) { + ICUResourceBundleReader poolBundleReader = getReader(baseName, "pool", loader); + if (!poolBundleReader.isPoolBundle) { + throw new IllegalStateException("pool.res is not a pool bundle"); + } + if (poolBundleReader.indexes[URES_INDEX_POOL_CHECKSUM] != indexes[URES_INDEX_POOL_CHECKSUM]) { + throw new IllegalStateException("pool.res has a different checksum than this bundle"); + } + poolBundleKeys = poolBundleReader.keyStrings; + poolBundleKeysAsString = poolBundleReader.keyStringsAsString; } } - static ICUResourceBundleReader getReader(String resolvedName, ClassLoader root) { - InputStream stream = ICUData.getStream(root,resolvedName); - - if(stream==null){ + + static ICUResourceBundleReader getReader(String baseName, String localeID, ClassLoader root) { + ReaderInfo info = new ReaderInfo(baseName, localeID, root); + ICUResourceBundleReader reader = CACHE.getInstance(info, info); + if (reader == NULL_READER) { return null; } - ICUResourceBundleReader reader = new ICUResourceBundleReader(stream, resolvedName); return reader; } - - void setPoolBundleKeys(ICUResourceBundleReader poolBundleReader) { - if(!poolBundleReader.isPoolBundle) { - throw new IllegalStateException("pool.res is not a pool bundle"); - } - if(poolBundleReader.indexes[URES_INDEX_POOL_CHECKSUM] != indexes[URES_INDEX_POOL_CHECKSUM]) { - throw new IllegalStateException("pool.res has a different checksum than this bundle"); - } - poolBundleKeys = poolBundleReader.keyStrings; - poolBundleKeysAsString = poolBundleReader.keyStringsAsString; - } // See res_init() in ICU4C/source/common/uresdata.c. private void readData(InputStream stream) throws IOException { @@ -859,4 +919,33 @@ public final class ICUResourceBundleReader implements ICUBinary.Authenticate { itemsOffset = offset + 4 * (1 + size); } } + + private static final String ICU_RESOURCE_SUFFIX = ".res"; + + /** + * Gets the full name of the resource with suffix. + */ + public static String getFullName(String baseName, String localeName) { + if (baseName == null || baseName.length() == 0) { + if (localeName.length() == 0) { + return localeName = ULocale.getDefault().toString(); + } + return localeName + ICU_RESOURCE_SUFFIX; + } else { + if (baseName.indexOf('.') == -1) { + if (baseName.charAt(baseName.length() - 1) != '/') { + return baseName + "/" + localeName + ICU_RESOURCE_SUFFIX; + } else { + return baseName + localeName + ICU_RESOURCE_SUFFIX; + } + } else { + baseName = baseName.replace('.', '/'); + if (localeName.length() == 0) { + return baseName + ICU_RESOURCE_SUFFIX; + } else { + return baseName + "_" + localeName + ICU_RESOURCE_SUFFIX; + } + } + } + } } diff --git a/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java b/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java index 84a6c0d382b..041f003c084 100644 --- a/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java +++ b/icu4j/main/classes/core/src/com/ibm/icu/util/UResourceBundle.java @@ -1,6 +1,6 @@ /* ******************************************************************************* - * Copyright (C) 2004-2010, International Business Machines Corporation and * + * Copyright (C) 2004-2011, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ @@ -21,6 +21,7 @@ import java.util.TreeSet; import com.ibm.icu.impl.ICUCache; import com.ibm.icu.impl.ICUResourceBundle; +import com.ibm.icu.impl.ICUResourceBundleReader; import com.ibm.icu.impl.ResourceBundleWrapper; import com.ibm.icu.impl.SimpleCache; @@ -541,7 +542,7 @@ public abstract class UResourceBundle extends ResourceBundle { { case ROOT_ICU: if(disableFallback) { - String fullName = ICUResourceBundle.getFullName(baseName, localeName); + String fullName = ICUResourceBundleReader.getFullName(baseName, localeName); b = loadFromCache(root, fullName, defaultLocale); if (b == null) { b = ICUResourceBundle.getBundleInstance(baseName, localeName, root, @@ -686,7 +687,7 @@ public abstract class UResourceBundle extends ResourceBundle { public UResourceBundle get(String aKey) { UResourceBundle obj = findTopLevel(aKey); if (obj == null) { - String fullName = ICUResourceBundle.getFullName(getBaseName(), getLocaleID()); + String fullName = ICUResourceBundleReader.getFullName(getBaseName(), getLocaleID()); throw new MissingResourceException( "Can't find resource for bundle " + fullName + ", key " + aKey, this.getClass().getName(), aKey);