7102969: currency.properties supercede not working correctly
authornishjain
Fri, 20 May 2016 13:48:58 +0900
changeset 38440 9e77c5b81def
parent 38439 8a3871cd7fca
child 38441 43ef784e3a96
7102969: currency.properties supercede not working correctly 8149452: j.t.SimpleDateFormat.getDateFormatSymbols().getZoneStrings() returns incorrect result for some time zones 8157138: Error while fetching currency instance by Currency.getInstance(currencycode) Reviewed-by: naoto, okutsu, peytoia
jdk/make/data/currency/CurrencyData.properties
jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java
jdk/make/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java
jdk/src/java.base/share/classes/java/util/Currency.java
jdk/test/java/util/Currency/PropertiesTest.java
jdk/test/java/util/Currency/PropertiesTest.sh
jdk/test/java/util/Currency/currency.properties
jdk/test/java/util/Currency/tablea1.txt
jdk/test/java/util/TimeZone/Bug8149452.java
--- a/jdk/make/data/currency/CurrencyData.properties	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/make/data/currency/CurrencyData.properties	Fri May 20 13:48:58 2016 +0900
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2016, 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
@@ -26,7 +26,8 @@
 # Version of the currency data format.
 #   1: initial
 #   2: Change in minor unit (allowing 4-9 digits)
-formatVersion=2
+#   3: Change in the order of special case and other currency entries
+formatVersion=3
 
 # Version of the currency code information in this class.
 # It is a serial number that accompanies with each amendment.
--- a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java	Fri May 20 13:48:58 2016 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, 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
@@ -584,7 +584,9 @@
                 String[] data = (String[])e[1];
 
                 if (map.get(TIMEZONE_ID_PREFIX + tzid) == null &&
-                    handlerMetaZones.get(tzid) == null) {
+                    handlerMetaZones.get(tzid) == null ||
+                    handlerMetaZones.get(tzid) != null &&
+                    map.get(METAZONE_ID_PREFIX + handlerMetaZones.get(tzid)) == null) {
                     // First, check the CLDR meta key
                     Optional<Map.Entry<String, String>> cldrMeta =
                         handlerMetaZones.getData().entrySet().stream()
--- a/jdk/make/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/make/src/classes/build/tools/generatecurrencydata/GenerateCurrencyData.java	Fri May 20 13:48:58 2016 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -121,7 +121,7 @@
 
     private static final int maxOtherCurrencies = 128;
     private static int otherCurrenciesCount = 0;
-    private static StringBuffer otherCurrencies = new StringBuffer();
+    private static String[] otherCurrencies = new String[maxOtherCurrencies];
     private static int[] otherCurrenciesDefaultFractionDigits = new int[maxOtherCurrencies];
     private static int[] otherCurrenciesNumericCode= new int[maxOtherCurrencies];
 
@@ -318,10 +318,7 @@
                 if (otherCurrenciesCount == maxOtherCurrencies) {
                     throw new RuntimeException("too many other currencies");
                 }
-                if (otherCurrencies.length() > 0) {
-                    otherCurrencies.append('-');
-                }
-                otherCurrencies.append(currencyCode);
+                otherCurrencies[otherCurrenciesCount] = currencyCode;
                 otherCurrenciesDefaultFractionDigits[otherCurrenciesCount] = getDefaultFractionDigits(currencyCode);
                 otherCurrenciesNumericCode[otherCurrenciesCount] = getNumericCode(currencyCode);
                 otherCurrenciesCount++;
@@ -350,35 +347,41 @@
         out.writeInt(Integer.parseInt(dataVersion));
         writeIntArray(mainTable, mainTable.length);
         out.writeInt(specialCaseCount);
-        writeLongArray(specialCaseCutOverTimes, specialCaseCount);
-        writeStringArray(specialCaseOldCurrencies, specialCaseCount);
-        writeStringArray(specialCaseNewCurrencies, specialCaseCount);
-        writeIntArray(specialCaseOldCurrenciesDefaultFractionDigits, specialCaseCount);
-        writeIntArray(specialCaseNewCurrenciesDefaultFractionDigits, specialCaseCount);
-        writeIntArray(specialCaseOldCurrenciesNumericCode, specialCaseCount);
-        writeIntArray(specialCaseNewCurrenciesNumericCode, specialCaseCount);
+        writeSpecialCaseEntries();
         out.writeInt(otherCurrenciesCount);
-        out.writeUTF(otherCurrencies.toString());
-        writeIntArray(otherCurrenciesDefaultFractionDigits, otherCurrenciesCount);
-        writeIntArray(otherCurrenciesNumericCode, otherCurrenciesCount);
+        writeOtherCurrencies();
     }
 
     private static void writeIntArray(int[] ia, int count) throws IOException {
-        for (int i = 0; i < count; i ++) {
+        for (int i = 0; i < count; i++) {
             out.writeInt(ia[i]);
         }
     }
 
-    private static void writeLongArray(long[] la, int count) throws IOException  {
-        for (int i = 0; i < count; i ++) {
-            out.writeLong(la[i]);
+    private static void writeSpecialCaseEntries() throws IOException {
+        for (int index = 0; index < specialCaseCount; index++) {
+            out.writeLong(specialCaseCutOverTimes[index]);
+            String str = (specialCaseOldCurrencies[index] != null)
+                    ? specialCaseOldCurrencies[index] : "";
+            out.writeUTF(str);
+            str = (specialCaseNewCurrencies[index] != null)
+                    ? specialCaseNewCurrencies[index] : "";
+            out.writeUTF(str);
+            out.writeInt(specialCaseOldCurrenciesDefaultFractionDigits[index]);
+            out.writeInt(specialCaseNewCurrenciesDefaultFractionDigits[index]);
+            out.writeInt(specialCaseOldCurrenciesNumericCode[index]);
+            out.writeInt(specialCaseNewCurrenciesNumericCode[index]);
         }
     }
 
-    private static void writeStringArray(String[] sa, int count) throws IOException  {
-        for (int i = 0; i < count; i ++) {
-            String str = (sa[i] != null) ? sa[i] : "";
+    private static void writeOtherCurrencies() throws IOException {
+        for (int index = 0; index < otherCurrenciesCount; index++) {
+            String str = (otherCurrencies[index] != null)
+                    ? otherCurrencies[index] : "";
             out.writeUTF(str);
+            out.writeInt(otherCurrenciesDefaultFractionDigits[index]);
+            out.writeInt(otherCurrenciesNumericCode[index]);
         }
     }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/Currency.java	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/src/java.base/share/classes/java/util/Currency.java	Fri May 20 13:48:58 2016 +0900
@@ -153,33 +153,13 @@
     //   - bits 0-4: final char for currency code for simple country, or ID of special case
     // - special case IDs:
     //   - 0: country has no currency
-    //   - other: index into sc* arrays + 1
-    // - scCutOverTimes: cut-over time in millis as returned by
-    //   System.currentTimeMillis for special case countries that are changing
-    //   currencies; Long.MAX_VALUE for countries that are not changing currencies
-    // - scOldCurrencies: old currencies for special case countries
-    // - scNewCurrencies: new currencies for special case countries that are
-    //   changing currencies; null for others
-    // - scOldCurrenciesDFD: default fraction digits for old currencies
-    // - scNewCurrenciesDFD: default fraction digits for new currencies, 0 for
-    //   countries that are not changing currencies
-    // - otherCurrencies: concatenation of all currency codes that are not the
-    //   main currency of a simple country, separated by "-"
-    // - otherCurrenciesDFD: decimal format digits for currencies in otherCurrencies, same order
+    //   - other: index into specialCasesList
 
     static int formatVersion;
     static int dataVersion;
     static int[] mainTable;
-    static long[] scCutOverTimes;
-    static String[] scOldCurrencies;
-    static String[] scNewCurrencies;
-    static int[] scOldCurrenciesDFD;
-    static int[] scNewCurrenciesDFD;
-    static int[] scOldCurrenciesNumericCode;
-    static int[] scNewCurrenciesNumericCode;
-    static String otherCurrencies;
-    static int[] otherCurrenciesDFD;
-    static int[] otherCurrenciesNumericCode;
+    static List<SpecialCaseEntry> specialCasesList;
+    static List<OtherCurrencyEntry> otherCurrenciesList;
 
     // handy constants - must match definitions in GenerateCurrencyData
     // magic number
@@ -214,7 +194,7 @@
     private static final int NUMERIC_CODE_SHIFT = 10;
 
     // Currency data format version
-    private static final int VALID_FORMAT_VERSION = 2;
+    private static final int VALID_FORMAT_VERSION = 3;
 
     static {
         AccessController.doPrivileged(new PrivilegedAction<>() {
@@ -236,17 +216,9 @@
                         dataVersion = dis.readInt();
                         mainTable = readIntArray(dis, A_TO_Z * A_TO_Z);
                         int scCount = dis.readInt();
-                        scCutOverTimes = readLongArray(dis, scCount);
-                        scOldCurrencies = readStringArray(dis, scCount);
-                        scNewCurrencies = readStringArray(dis, scCount);
-                        scOldCurrenciesDFD = readIntArray(dis, scCount);
-                        scNewCurrenciesDFD = readIntArray(dis, scCount);
-                        scOldCurrenciesNumericCode = readIntArray(dis, scCount);
-                        scNewCurrenciesNumericCode = readIntArray(dis, scCount);
+                        specialCasesList = readSpecialCases(dis, scCount);
                         int ocCount = dis.readInt();
-                        otherCurrencies = dis.readUTF();
-                        otherCurrenciesDFD = readIntArray(dis, ocCount);
-                        otherCurrenciesNumericCode = readIntArray(dis, ocCount);
+                        otherCurrenciesList = readOtherCurrencies(dis, ocCount);
                     }
                 } catch (IOException e) {
                     throw new InternalError(e);
@@ -329,6 +301,7 @@
             // Currency code not internally generated, need to verify first
             // A currency code must have 3 characters and exist in the main table
             // or in the list of other currencies.
+            boolean found = false;
             if (currencyCode.length() != 3) {
                 throw new IllegalArgumentException();
             }
@@ -340,17 +313,23 @@
                     && currencyCode.charAt(2) - 'A' == (tableEntry & SIMPLE_CASE_COUNTRY_FINAL_CHAR_MASK)) {
                 defaultFractionDigits = (tableEntry & SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_MASK) >> SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT;
                 numericCode = (tableEntry & NUMERIC_CODE_MASK) >> NUMERIC_CODE_SHIFT;
-            } else {
-                // Check for '-' separately so we don't get false hits in the table.
-                if (currencyCode.charAt(2) == '-') {
+                found = true;
+            } else { //special case
+                int[] fractionAndNumericCode = SpecialCaseEntry.findEntry(currencyCode);
+                if (fractionAndNumericCode != null) {
+                    defaultFractionDigits = fractionAndNumericCode[0];
+                    numericCode = fractionAndNumericCode[1];
+                    found = true;
+                }
+            }
+
+            if (!found) {
+                OtherCurrencyEntry ocEntry = OtherCurrencyEntry.findEntry(currencyCode);
+                if (ocEntry == null) {
                     throw new IllegalArgumentException();
                 }
-                int index = otherCurrencies.indexOf(currencyCode);
-                if (index == -1) {
-                    throw new IllegalArgumentException();
-                }
-                defaultFractionDigits = otherCurrenciesDFD[index / 4];
-                numericCode = otherCurrenciesNumericCode[index / 4];
+                defaultFractionDigits = ocEntry.fraction;
+                numericCode = ocEntry.numericCode;
             }
         }
 
@@ -410,13 +389,17 @@
             if (tableEntry == COUNTRY_WITHOUT_CURRENCY_ENTRY) {
                 return null;
             } else {
-                int index = (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK) - SPECIAL_CASE_COUNTRY_INDEX_DELTA;
-                if (scCutOverTimes[index] == Long.MAX_VALUE || System.currentTimeMillis() < scCutOverTimes[index]) {
-                    return getInstance(scOldCurrencies[index], scOldCurrenciesDFD[index],
-                        scOldCurrenciesNumericCode[index]);
+                int index = SpecialCaseEntry.toIndex(tableEntry);
+                SpecialCaseEntry scEntry = specialCasesList.get(index);
+                if (scEntry.cutOverTime == Long.MAX_VALUE
+                        || System.currentTimeMillis() < scEntry.cutOverTime) {
+                    return getInstance(scEntry.oldCurrency,
+                            scEntry.oldCurrencyFraction,
+                            scEntry.oldCurrencyNumericCode);
                 } else {
-                    return getInstance(scNewCurrencies[index], scNewCurrenciesDFD[index],
-                        scNewCurrenciesNumericCode[index]);
+                    return getInstance(scEntry.newCurrency,
+                            scEntry.newCurrencyFraction,
+                            scEntry.newCurrencyNumericCode);
                 }
             }
         }
@@ -451,14 +434,29 @@
                             sb.append(c2);
                             sb.append(finalChar);
                             available.add(getInstance(sb.toString(), defaultFractionDigits, numericCode));
+                        } else if ((tableEntry & COUNTRY_TYPE_MASK) == SPECIAL_CASE_COUNTRY_MASK
+                                && tableEntry != INVALID_COUNTRY_ENTRY
+                                && tableEntry != COUNTRY_WITHOUT_CURRENCY_ENTRY) {
+                            int index = SpecialCaseEntry.toIndex(tableEntry);
+                            SpecialCaseEntry scEntry = specialCasesList.get(index);
+
+                            if (scEntry.cutOverTime == Long.MAX_VALUE
+                                    || System.currentTimeMillis() < scEntry.cutOverTime) {
+                                available.add(getInstance(scEntry.oldCurrency,
+                                        scEntry.oldCurrencyFraction,
+                                        scEntry.oldCurrencyNumericCode));
+                            } else {
+                                available.add(getInstance(scEntry.newCurrency,
+                                        scEntry.newCurrencyFraction,
+                                        scEntry.newCurrencyNumericCode));
+                            }
                         }
                     }
                 }
 
                 // Now add other currencies
-                StringTokenizer st = new StringTokenizer(otherCurrencies, "-");
-                while (st.hasMoreElements()) {
-                    available.add(getInstance((String)st.nextElement()));
+                for (OtherCurrencyEntry entry : otherCurrenciesList) {
+                    available.add(getInstance(entry.currencyCode));
                 }
             }
         }
@@ -521,15 +519,15 @@
     }
 
     /**
-    * Gets the default number of fraction digits used with this currency.
-    * Note that the number of fraction digits is the same as ISO 4217's
-    * minor unit for the currency.
-    * For example, the default number of fraction digits for the Euro is 2,
-    * while for the Japanese Yen it's 0.
-    * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
-    * -1 is returned.
-    *
-    * @return the default number of fraction digits used with this currency
+     * Gets the default number of fraction digits used with this currency.
+     * Note that the number of fraction digits is the same as ISO 4217's
+     * minor unit for the currency.
+     * For example, the default number of fraction digits for the Euro is 2,
+     * while for the Japanese Yen it's 0.
+     * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
+     * -1 is returned.
+     *
+     * @return the default number of fraction digits used with this currency
     */
     public int getDefaultFractionDigits() {
         return defaultFractionDigits;
@@ -693,22 +691,55 @@
         return ret;
     }
 
-    private static long[] readLongArray(DataInputStream dis, int count) throws IOException {
-        long[] ret = new long[count];
+    private static List<SpecialCaseEntry> readSpecialCases(DataInputStream dis,
+            int count)
+            throws IOException {
+
+        List<SpecialCaseEntry> list = new ArrayList<>(count);
+        long cutOverTime;
+        String oldCurrency;
+        String newCurrency;
+        int oldCurrencyFraction;
+        int newCurrencyFraction;
+        int oldCurrencyNumericCode;
+        int newCurrencyNumericCode;
+
         for (int i = 0; i < count; i++) {
-            ret[i] = dis.readLong();
+            cutOverTime = dis.readLong();
+            oldCurrency = dis.readUTF();
+            newCurrency = dis.readUTF();
+            oldCurrencyFraction = dis.readInt();
+            newCurrencyFraction = dis.readInt();
+            oldCurrencyNumericCode = dis.readInt();
+            newCurrencyNumericCode = dis.readInt();
+            SpecialCaseEntry sc = new SpecialCaseEntry(cutOverTime,
+                    oldCurrency, newCurrency,
+                    oldCurrencyFraction, newCurrencyFraction,
+                    oldCurrencyNumericCode, newCurrencyNumericCode);
+            list.add(sc);
         }
-
-        return ret;
+        return list;
     }
 
-    private static String[] readStringArray(DataInputStream dis, int count) throws IOException {
-        String[] ret = new String[count];
+    private static List<OtherCurrencyEntry> readOtherCurrencies(DataInputStream dis,
+            int count)
+            throws IOException {
+
+        List<OtherCurrencyEntry> list = new ArrayList<>(count);
+        String currencyCode;
+        int fraction;
+        int numericCode;
+
         for (int i = 0; i < count; i++) {
-            ret[i] = dis.readUTF();
+            currencyCode = dis.readUTF();
+            fraction = dis.readInt();
+            numericCode = dis.readInt();
+            OtherCurrencyEntry oc = new OtherCurrencyEntry(currencyCode,
+                    fraction,
+                    numericCode);
+            list.add(oc);
         }
-
-        return ret;
+        return list;
     }
 
     /**
@@ -766,21 +797,27 @@
             return;
         }
 
-        int index;
-        for (index = 0; index < scOldCurrencies.length; index++) {
-            if (scOldCurrencies[index].equals(code)) {
-                break;
-            }
+        int index = SpecialCaseEntry.indexOf(code, fraction, numeric);
+
+        /* if a country switches from simple case to special case or
+         * one special case to other special case which is not present
+         * in the sc arrays then insert the new entry in special case arrays
+         */
+        if (index == -1 && (ctry.charAt(0) != code.charAt(0)
+                || ctry.charAt(1) != code.charAt(1))) {
+
+            specialCasesList.add(new SpecialCaseEntry(code, fraction, numeric));
+            index = specialCasesList.size() - 1;
         }
 
-        if (index == scOldCurrencies.length) {
+        if (index == -1) {
             // simple case
-            entry |= (fraction << SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT) |
-                     (code.charAt(2) - 'A');
+            entry |= (fraction << SIMPLE_CASE_COUNTRY_DEFAULT_DIGITS_SHIFT)
+                    | (code.charAt(2) - 'A');
         } else {
             // special case
-            entry |= SPECIAL_CASE_COUNTRY_MASK |
-                     (index + SPECIAL_CASE_COUNTRY_INDEX_DELTA);
+            entry = SPECIAL_CASE_COUNTRY_MASK
+                    | (index + SPECIAL_CASE_COUNTRY_INDEX_DELTA);
         }
         setMainTableEntry(ctry.charAt(0), ctry.charAt(1), entry);
     }
@@ -814,5 +851,128 @@
             }
         }
     }
+
+    /* Used to represent a special case currency entry
+     * - cutOverTime: cut-over time in millis as returned by
+     *   System.currentTimeMillis for special case countries that are changing
+     *   currencies; Long.MAX_VALUE for countries that are not changing currencies
+     * - oldCurrency: old currencies for special case countries
+     * - newCurrency: new currencies for special case countries that are
+     *   changing currencies; null for others
+     * - oldCurrencyFraction: default fraction digits for old currencies
+     * - newCurrencyFraction: default fraction digits for new currencies, 0 for
+     *   countries that are not changing currencies
+     * - oldCurrencyNumericCode: numeric code for old currencies
+     * - newCurrencyNumericCode: numeric code for new currencies, 0 for countries
+     *   that are not changing currencies
+    */
+    private static class SpecialCaseEntry {
+
+        final private long cutOverTime;
+        final private String oldCurrency;
+        final private String newCurrency;
+        final private int oldCurrencyFraction;
+        final private int newCurrencyFraction;
+        final private int oldCurrencyNumericCode;
+        final private int newCurrencyNumericCode;
+
+        private SpecialCaseEntry(long cutOverTime, String oldCurrency, String newCurrency,
+                int oldCurrencyFraction, int newCurrencyFraction,
+                int oldCurrencyNumericCode, int newCurrencyNumericCode) {
+            this.cutOverTime = cutOverTime;
+            this.oldCurrency = oldCurrency;
+            this.newCurrency = newCurrency;
+            this.oldCurrencyFraction = oldCurrencyFraction;
+            this.newCurrencyFraction = newCurrencyFraction;
+            this.oldCurrencyNumericCode = oldCurrencyNumericCode;
+            this.newCurrencyNumericCode = newCurrencyNumericCode;
+        }
+
+        private SpecialCaseEntry(String currencyCode, int fraction,
+                int numericCode) {
+            this(Long.MAX_VALUE, currencyCode, "", fraction, 0, numericCode, 0);
+        }
+
+        //get the index of the special case entry
+        private static int indexOf(String code, int fraction, int numeric) {
+            int size = specialCasesList.size();
+            for (int index = 0; index < size; index++) {
+                SpecialCaseEntry scEntry = specialCasesList.get(index);
+                if (scEntry.oldCurrency.equals(code)
+                        && scEntry.oldCurrencyFraction == fraction
+                        && scEntry.oldCurrencyNumericCode == numeric
+                        && scEntry.cutOverTime == Long.MAX_VALUE) {
+                    return index;
+                }
+            }
+            return -1;
+        }
+
+        // get the fraction and numericCode of the sc currencycode
+        private static int[] findEntry(String code) {
+            int[] fractionAndNumericCode = null;
+            int size = specialCasesList.size();
+            for (int index = 0; index < size; index++) {
+                SpecialCaseEntry scEntry = specialCasesList.get(index);
+                if (scEntry.oldCurrency.equals(code) && (scEntry.cutOverTime == Long.MAX_VALUE
+                        || System.currentTimeMillis() < scEntry.cutOverTime)) {
+                    //consider only when there is no new currency or cutover time is not passed
+                    fractionAndNumericCode = new int[2];
+                    fractionAndNumericCode[0] = scEntry.oldCurrencyFraction;
+                    fractionAndNumericCode[1] = scEntry.oldCurrencyNumericCode;
+                    break;
+                } else if (scEntry.newCurrency.equals(code)
+                        && System.currentTimeMillis() >= scEntry.cutOverTime) {
+                    //consider only if the cutover time is passed
+                    fractionAndNumericCode = new int[2];
+                    fractionAndNumericCode[0] = scEntry.newCurrencyFraction;
+                    fractionAndNumericCode[1] = scEntry.newCurrencyNumericCode;
+                    break;
+                }
+            }
+            return fractionAndNumericCode;
+        }
+
+        // convert the special case entry to sc arrays index
+        private static int toIndex(int tableEntry) {
+            return (tableEntry & SPECIAL_CASE_COUNTRY_INDEX_MASK) - SPECIAL_CASE_COUNTRY_INDEX_DELTA;
+        }
+
+    }
+
+    /* Used to represent Other currencies
+     * - currencyCode: currency codes that are not the main currency
+     *   of a simple country
+     * - otherCurrenciesDFD: decimal format digits for other currencies
+     * - otherCurrenciesNumericCode: numeric code for other currencies
+     */
+    private static class OtherCurrencyEntry {
+
+        final private String currencyCode;
+        final private int fraction;
+        final private int numericCode;
+
+        private OtherCurrencyEntry(String currencyCode, int fraction,
+                int numericCode) {
+            this.currencyCode = currencyCode;
+            this.fraction = fraction;
+            this.numericCode = numericCode;
+        }
+
+        //get the instance of the other currency code
+        private static OtherCurrencyEntry findEntry(String code) {
+            int size = otherCurrenciesList.size();
+            for (int index = 0; index < size; index++) {
+                OtherCurrencyEntry ocEntry = otherCurrenciesList.get(index);
+                if (ocEntry.currencyCode.equalsIgnoreCase(code)) {
+                    return ocEntry;
+                }
+            }
+            return null;
+        }
+
+    }
+
 }
 
+
--- a/jdk/test/java/util/Currency/PropertiesTest.java	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/test/java/util/Currency/PropertiesTest.java	Fri May 20 13:48:58 2016 +0900
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -25,6 +25,7 @@
 import java.text.*;
 import java.util.*;
 import java.util.regex.*;
+import java.util.stream.Collectors;
 
 public class PropertiesTest {
     public static void main(String[] args) throws Exception {
@@ -32,9 +33,14 @@
             dump(args[1]);
         } else if (args.length == 4 && args[0].equals("-c")) {
             compare(args[1], args[2], args[3]);
+        } else if (args.length == 1 && args[0].equals("bug7102969")) {
+            bug7102969();
+        } else if (args.length == 1 && args[0].equals("bug8157138")) {
+            bug8157138();
         } else {
             System.err.println("Usage:  java PropertiesTest -d <dumpfile>");
             System.err.println("        java PropertiesTest -c <beforedump> <afterdump> <propsfile>");
+            System.err.println("        java PropertiesTest bug[JBS bug id number] e.g. bug7102969");
             System.exit(-1);
         }
     }
@@ -174,6 +180,74 @@
         }
     }
 
+    private static void bug7102969() {
+
+        // check the correct overriding of special case entries
+        Currency cur = Currency.getInstance(new Locale("", "JP"));
+        if (!cur.getCurrencyCode().equals("ABC")) {
+            throw new RuntimeException("[Expected: ABC as currency code of JP, found: "
+                    + cur.getCurrencyCode() + "]");
+        }
+
+        /* check if the currency instance is returned by
+         * getAvailableCurrencies() method
+         */
+        if (!Currency.getAvailableCurrencies().contains(cur)) {
+            throw new RuntimeException("[The Currency instance ["
+                    + cur.getCurrencyCode() + ", "
+                    + cur.getNumericCode() + ", "
+                    + cur.getDefaultFractionDigits()
+                    + "] is not available in the currencies list]");
+        }
+
+    }
+
+    private static void bug8157138() {
+
+        /* check the currencies which exist only as a special case are
+         * accessible i.e. it should not throw IllegalArgumentException
+         */
+        try {
+            Currency.getInstance("MAD");
+        } catch (IllegalArgumentException ex) {
+            throw new RuntimeException("Test Failed: "
+                    + "special case currency instance MAD not found"
+                    + " via Currency.getInstance(\"MAD\")");
+        }
+
+        try {
+            Currency.getInstance("ABC");
+        } catch (IllegalArgumentException ex) {
+            throw new RuntimeException("Test Failed: "
+                    + "special case currency instance ABC not found"
+                    + " via Currency.getInstance(\"ABC\")");
+        }
+
+        /* check the currency value is returned by getAvailableCurrencies()
+         * method
+        */
+        List<Currency> list = Currency.getAvailableCurrencies().stream()
+                .filter(cur -> cur.getCurrencyCode().equals("MAD"))
+                .collect(Collectors.toList());
+
+        if (list.isEmpty()) {
+            throw new RuntimeException("Test Failed: "
+                    + "special case currency instance MAD not found"
+                    + " in Currency.getAvailableCurrencies() list");
+        }
+
+        list = Currency.getAvailableCurrencies().stream()
+                .filter(cur -> cur.getCurrencyCode().equals("ABC"))
+                .collect(Collectors.toList());
+
+        if (list.isEmpty()) {
+            throw new RuntimeException("Test Failed: "
+                    + "special case currency instance ABC not found"
+                    + " in Currency.getAvailableCurrencies() list");
+        }
+
+    }
+
     private static boolean isPastCutoverDate(String s)
             throws IndexOutOfBoundsException, NullPointerException, ParseException {
         String dateString = s.substring(s.lastIndexOf(',')+1, s.length()).trim();
--- a/jdk/test/java/util/Currency/PropertiesTest.sh	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/test/java/util/Currency/PropertiesTest.sh	Fri May 20 13:48:58 2016 +0900
@@ -23,7 +23,8 @@
 #
 
 # @test
-# @bug 6332666 6863624 7180362 8003846 8074350 8074351 8130246 8149735
+# @bug 6332666 6863624 7180362 8003846 8074350 8074351 8130246 8149735 7102969
+#      8157138
 # @summary tests the capability of replacing the currency data with user
 #     specified currency properties file
 # @build PropertiesTest
@@ -113,6 +114,16 @@
 if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
 if [ ! -f dump3 ]; then  echo "file dump3 not created. Test cannot execute.  Failed."; exit 1; fi
 
+# run bug7102969 test
+echo ''
+${WRITABLEJDK}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} PropertiesTest bug7102969
+if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+
+# run bug8157138 test
+echo ''
+${WRITABLEJDK}${FS}bin${FS}java ${TESTVMOPTS} -cp ${TESTCLASSES} PropertiesTest bug8157138
+if [ $? != 0 ]; then failures=`expr $failures + 1`; fi
+
 # Cleanup
 rm -rf $WRITABLEJDK
 
--- a/jdk/test/java/util/Currency/currency.properties	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/test/java/util/Currency/currency.properties	Fri May 20 13:48:58 2016 +0900
@@ -6,7 +6,7 @@
 CL=CLF,990,4
 CM=IED,111,2, 2004-01-01T00:70:00
 ES=ESD,877,2
-JP=JPZ,123,2
+JP=ABC,999,0
 MA=MAA,555,5
 MC=MCC,555,6
 MD=MDD,555,7
--- a/jdk/test/java/util/Currency/tablea1.txt	Fri May 20 11:20:49 2016 +0800
+++ b/jdk/test/java/util/Currency/tablea1.txt	Fri May 20 13:48:58 2016 +0900
@@ -5,7 +5,7 @@
 #
 
 # Version
-FILEVERSION=2
+FILEVERSION=3
 DATAVERSION=160
 
 # ISO 4217 currency data
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/TimeZone/Bug8149452.java	Fri May 20 13:48:58 2016 +0900
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+/*
+ * @test
+ * @bug 8149452
+ * @summary Check the missing time zone names.
+ */
+import java.text.DateFormatSymbols;
+import java.util.ArrayList;
+import java.util.TimeZone;
+import java.util.Arrays;
+import java.util.List;
+
+public class Bug8149452 {
+
+    public static void main(String[] args) {
+
+        List<String> listNotFound = new ArrayList<>();
+        String[][] zoneStrings = DateFormatSymbols.getInstance()
+                .getZoneStrings();
+        for (String tzID : TimeZone.getAvailableIDs()) {
+            if (!Arrays.stream(zoneStrings)
+                    .anyMatch(zone -> tzID.equalsIgnoreCase(zone[0]))) {
+                // to ignore names for Etc/GMT[+-][0-9]+ which are not supported
+                if (!tzID.startsWith("Etc/GMT") && !tzID.startsWith("GMT")) {
+                    listNotFound.add(tzID);
+                }
+            }
+        }
+
+        if (!listNotFound.isEmpty()) {
+            throw new RuntimeException("Test Failed: Time Zone Strings for "
+                    + listNotFound + " not found");
+        }
+
+    }
+
+}