39 import java.util.concurrent.ConcurrentHashMap; 40 import java.util.concurrent.ConcurrentMap; 41 import java.util.regex.Pattern; 42 import java.util.regex.Matcher; 43 import java.util.spi.CurrencyNameProvider; 44 import sun.util.locale.provider.LocaleServiceProviderPool; 45 import sun.util.logging.PlatformLogger; 46 47 48 /** 49 * Represents a currency. Currencies are identified by their ISO 4217 currency 50 * codes. Visit the <a href="http://www.iso.org/iso/en/prods-services/popstds/currencycodes.html"> 51 * ISO web site</a> for more information, including a table of 52 * currency codes. 53 * <p> 54 * The class is designed so that there's never more than one 55 * <code>Currency</code> instance for any given currency. Therefore, there's 56 * no public constructor. You obtain a <code>Currency</code> instance using 57 * the <code>getInstance</code> methods. 58 * <p> 59 * Users can supersede the Java runtime currency data by creating a properties 60 * file named <code><JAVA_HOME>/lib/currency.properties</code>. The contents 61 * of the properties file are key/value pairs of the ISO 3166 country codes 62 * and the ISO 4217 currency data respectively. The value part consists of 63 * three ISO 4217 values of a currency, i.e., an alphabetic code, a numeric 64 * code, and a minor unit. Those three ISO 4217 values are separated by commas. 65 * The lines which start with '#'s are considered comment lines. An optional UTC 66 * timestamp may be specified per currency entry if users need to specify a 67 * cutover date indicating when the new data comes into effect. The timestamp is 68 * appended to the end of the currency properties and uses a comma as a separator. 69 * If a UTC datestamp is present and valid, the JRE will only use the new currency 70 * properties if the current UTC date is later than the date specified at class 71 * loading time. The format of the timestamp must be of ISO 8601 format : 72 * {@code 'yyyy-MM-dd'T'HH:mm:ss'}. For example, 73 * <p> 74 * <code> 75 * #Sample currency properties<br> 76 * JP=JPZ,999,0 77 * </code> 78 * <p> 79 * will supersede the currency data for Japan. 80 * 81 * <p> 82 * <code> 83 * #Sample currency properties with cutover date<br> 84 * JP=JPZ,999,0,2014-01-01T00:00:00 229 dataVersion = dis.readInt(); 230 mainTable = readIntArray(dis, A_TO_Z * A_TO_Z); 231 int scCount = dis.readInt(); 232 scCutOverTimes = readLongArray(dis, scCount); 233 scOldCurrencies = readStringArray(dis, scCount); 234 scNewCurrencies = readStringArray(dis, scCount); 235 scOldCurrenciesDFD = readIntArray(dis, scCount); 236 scNewCurrenciesDFD = readIntArray(dis, scCount); 237 scOldCurrenciesNumericCode = readIntArray(dis, scCount); 238 scNewCurrenciesNumericCode = readIntArray(dis, scCount); 239 int ocCount = dis.readInt(); 240 otherCurrencies = dis.readUTF(); 241 otherCurrenciesDFD = readIntArray(dis, ocCount); 242 otherCurrenciesNumericCode = readIntArray(dis, ocCount); 243 } 244 } catch (IOException e) { 245 throw new InternalError(e); 246 } 247 248 // look for the properties file for overrides 249 try { 250 File propFile = new File(homeDir + File.separator + 251 "lib" + File.separator + 252 "currency.properties"); 253 if (propFile.exists()) { 254 Properties props = new Properties(); 255 try (FileReader fr = new FileReader(propFile)) { 256 props.load(fr); 257 } 258 Set<String> keys = props.stringPropertyNames(); 259 Pattern propertiesPattern = 260 Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*" + 261 "([0-3])\\s*,?\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:" + 262 "\\d{2}:\\d{2})?"); 263 for (String key : keys) { 264 replaceCurrencyData(propertiesPattern, 265 key.toUpperCase(Locale.ROOT), 266 props.getProperty(key).toUpperCase(Locale.ROOT)); 267 } 268 } 269 } catch (IOException e) { 270 info("currency.properties is ignored because of an IOException", e); 271 } 272 return null; | 39 import java.util.concurrent.ConcurrentHashMap; 40 import java.util.concurrent.ConcurrentMap; 41 import java.util.regex.Pattern; 42 import java.util.regex.Matcher; 43 import java.util.spi.CurrencyNameProvider; 44 import sun.util.locale.provider.LocaleServiceProviderPool; 45 import sun.util.logging.PlatformLogger; 46 47 48 /** 49 * Represents a currency. Currencies are identified by their ISO 4217 currency 50 * codes. Visit the <a href="http://www.iso.org/iso/en/prods-services/popstds/currencycodes.html"> 51 * ISO web site</a> for more information, including a table of 52 * currency codes. 53 * <p> 54 * The class is designed so that there's never more than one 55 * <code>Currency</code> instance for any given currency. Therefore, there's 56 * no public constructor. You obtain a <code>Currency</code> instance using 57 * the <code>getInstance</code> methods. 58 * <p> 59 * Users can supersede the Java runtime currency data by means of the system 60 * property {@code java.util.currency.data}. If this system property is 61 * defined then its value is the location of a properties file, the contents of 62 * which are key/value pairs of the ISO 3166 country codes and the ISO 4217 63 * currency data respectively. The value part consists of three ISO 4217 values 64 * of a currency, i.e., an alphabetic code, a numeric code, and a minor unit. 65 * Those three ISO 4217 values are separated by commas. 66 * The lines which start with '#'s are considered comment lines. An optional UTC 67 * timestamp may be specified per currency entry if users need to specify a 68 * cutover date indicating when the new data comes into effect. The timestamp is 69 * appended to the end of the currency properties and uses a comma as a separator. 70 * If a UTC datestamp is present and valid, the JRE will only use the new currency 71 * properties if the current UTC date is later than the date specified at class 72 * loading time. The format of the timestamp must be of ISO 8601 format : 73 * {@code 'yyyy-MM-dd'T'HH:mm:ss'}. For example, 74 * <p> 75 * <code> 76 * #Sample currency properties<br> 77 * JP=JPZ,999,0 78 * </code> 79 * <p> 80 * will supersede the currency data for Japan. 81 * 82 * <p> 83 * <code> 84 * #Sample currency properties with cutover date<br> 85 * JP=JPZ,999,0,2014-01-01T00:00:00 230 dataVersion = dis.readInt(); 231 mainTable = readIntArray(dis, A_TO_Z * A_TO_Z); 232 int scCount = dis.readInt(); 233 scCutOverTimes = readLongArray(dis, scCount); 234 scOldCurrencies = readStringArray(dis, scCount); 235 scNewCurrencies = readStringArray(dis, scCount); 236 scOldCurrenciesDFD = readIntArray(dis, scCount); 237 scNewCurrenciesDFD = readIntArray(dis, scCount); 238 scOldCurrenciesNumericCode = readIntArray(dis, scCount); 239 scNewCurrenciesNumericCode = readIntArray(dis, scCount); 240 int ocCount = dis.readInt(); 241 otherCurrencies = dis.readUTF(); 242 otherCurrenciesDFD = readIntArray(dis, ocCount); 243 otherCurrenciesNumericCode = readIntArray(dis, ocCount); 244 } 245 } catch (IOException e) { 246 throw new InternalError(e); 247 } 248 249 // look for the properties file for overrides 250 String propsFile = System.getProperty("java.util.currency.data"); 251 if (propsFile == null) { 252 propsFile = homeDir + File.separator + "lib" + 253 File.separator + "currency.properties"; 254 } 255 try { 256 File propFile = new File(propsFile); 257 if (propFile.exists()) { 258 Properties props = new Properties(); 259 try (FileReader fr = new FileReader(propFile)) { 260 props.load(fr); 261 } 262 Set<String> keys = props.stringPropertyNames(); 263 Pattern propertiesPattern = 264 Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*" + 265 "([0-3])\\s*,?\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:" + 266 "\\d{2}:\\d{2})?"); 267 for (String key : keys) { 268 replaceCurrencyData(propertiesPattern, 269 key.toUpperCase(Locale.ROOT), 270 props.getProperty(key).toUpperCase(Locale.ROOT)); 271 } 272 } 273 } catch (IOException e) { 274 info("currency.properties is ignored because of an IOException", e); 275 } 276 return null; |