1 /*
   2  * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 import java.io.*;
  25 import java.text.*;
  26 import java.util.*;
  27 import java.util.regex.*;
  28 
  29 public class PropertiesTest {
  30     public static void main(String[] args) throws Exception {
  31         if (args.length == 2 && args[0].equals("-d")) {
  32             dump(args[1]);
  33         } else if (args.length == 4 && args[0].equals("-c")) {
  34             compare(args[1], args[2], args[3]);
  35         } else {
  36             System.err.println("Usage:  java PropertiesTest -d <dumpfile>");
  37             System.err.println("        java PropertiesTest -c <beforedump> <afterdump> <propsfile>");
  38             System.exit(-1);
  39         }
  40     }
  41 
  42     private static void dump(String outfile) {
  43         File f = new File(outfile);
  44         PrintWriter pw;
  45         try {
  46             f.createNewFile();
  47             pw = new PrintWriter(f);
  48         } catch (Exception fnfe) {
  49             throw new RuntimeException(fnfe);
  50         }
  51         for (char c1 = 'A'; c1 <= 'Z'; c1++) {
  52             for (char c2 = 'A'; c2 <= 'Z'; c2++) {
  53                 String ctry = new StringBuilder().append(c1).append(c2).toString();
  54                 try {
  55                     Currency c = Currency.getInstance(new Locale("", ctry));
  56                     if (c != null) {
  57                         pw.printf(Locale.ROOT, "%s=%s,%03d,%1d\n",
  58                             ctry,
  59                             c.getCurrencyCode(),
  60                             c.getNumericCode(),
  61                             c.getDefaultFractionDigits());
  62                     }
  63                 } catch (IllegalArgumentException iae) {
  64                     // invalid country code
  65                     continue;
  66                 }
  67             }
  68         }
  69         pw.flush();
  70         pw.close();
  71     }
  72 
  73     private static void compare(String beforeFile, String afterFile, String propsFile)
  74         throws IOException
  75     {
  76         // load file contents
  77         Properties before = new Properties();
  78         try (Reader reader = new FileReader(beforeFile)) {
  79             before.load(reader);
  80         }
  81         Properties after = new Properties();
  82         try (Reader reader = new FileReader(afterFile)) {
  83             after.load(reader);
  84         }
  85 
  86         // remove the same contents from the 'after' properties
  87         Set<String> keys = before.stringPropertyNames();
  88         for (String key: keys) {
  89             String beforeVal = before.getProperty(key);
  90             String afterVal = after.getProperty(key);
  91             System.out.printf("Removing country: %s. before: %s, after: %s", key, beforeVal, afterVal);
  92             if (beforeVal.equals(afterVal)) {
  93                 after.remove(key);
  94                 System.out.printf(" --- removed\n");
  95             } else {
  96                 System.out.printf(" --- NOT removed\n");
  97             }
  98         }
  99 
 100         // now look at the currency.properties
 101         Properties p = new Properties();
 102         try (Reader reader = new FileReader(propsFile)) {
 103             p.load(reader);
 104         }
 105 
 106         // test each replacements
 107         keys = p.stringPropertyNames();
 108         Pattern propertiesPattern =
 109             Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*" +
 110                 "(\\d+)\\s*,?\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:" +
 111                 "\\d{2}:\\d{2})?");
 112         for (String key: keys) {
 113             String val = p.getProperty(key);
 114             try {
 115                 if (countOccurrences(val, ',') == 3 && !isPastCutoverDate(val)) {
 116                     System.out.println("Skipping since date is in future");
 117                     continue; // skip since date in future (no effect)
 118                 }
 119             } catch (ParseException pe) {
 120                 // swallow - currency class should not honour this value
 121                 continue;
 122             }
 123             String afterVal = after.getProperty(key);
 124             System.out.printf("Testing key: %s, val: %s... ", key, val);
 125             System.out.println("AfterVal is : " + afterVal);
 126 
 127             Matcher m = propertiesPattern.matcher(val.toUpperCase(Locale.ROOT));
 128             if (!m.find()) {
 129                 // format is not recognized.
 130                 System.out.printf("Format is not recognized.\n");
 131                 if (afterVal != null) {
 132                     throw new RuntimeException("Currency data replacement for "+key+" failed: It was incorrectly altered to "+afterVal);
 133                 }
 134 
 135                 // ignore this
 136                 continue;
 137             }
 138 
 139             String code = m.group(1);
 140             int numeric = Integer.parseInt(m.group(2));
 141             int fraction = Integer.parseInt(m.group(3));
 142             if (fraction > 9) {
 143                 System.out.println("Skipping since the fraction is greater than 9");
 144                 continue;
 145             }
 146 
 147             Matcher mAfter = propertiesPattern.matcher(afterVal);
 148             mAfter.find();
 149 
 150             String codeAfter = mAfter.group(1);
 151             int numericAfter = Integer.parseInt(mAfter.group(2));
 152             int fractionAfter = Integer.parseInt(mAfter.group(3));
 153             if (code.equals(codeAfter) &&
 154                 (numeric == numericAfter)&&
 155                 (fraction == fractionAfter)) {
 156                 after.remove(key);
 157             } else {
 158                 throw new RuntimeException("Currency data replacement for "+key+" failed: actual: (alphacode: "+codeAfter+", numcode: "+numericAfter+", fraction: "+fractionAfter+"), expected:  (alphacode: "+code+", numcode: "+numeric+", fraction: "+fraction+")");
 159             }
 160             System.out.printf("Success!\n");
 161         }
 162         if (!after.isEmpty()) {
 163             StringBuilder sb = new StringBuilder()
 164                 .append("Currency data replacement failed.  Unnecessary modification was(were) made for the following currencies:\n");
 165             keys = after.stringPropertyNames();
 166             for (String key : keys) {
 167                 sb.append("    country: ")
 168                 .append(key)
 169                 .append(" currency: ")
 170                 .append(after.getProperty(key))
 171                 .append("\n");
 172             }
 173             throw new RuntimeException(sb.toString());
 174         }
 175     }
 176 
 177     private static boolean isPastCutoverDate(String s)
 178             throws IndexOutOfBoundsException, NullPointerException, ParseException {
 179         String dateString = s.substring(s.lastIndexOf(',')+1, s.length()).trim();
 180         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT);
 181         format.setTimeZone(TimeZone.getTimeZone("GMT"));
 182         format.setLenient(false);
 183 
 184         long time = format.parse(dateString).getTime();
 185         if (System.currentTimeMillis() - time >= 0L) {
 186             return true;
 187         } else {
 188             return false;
 189         }
 190     }
 191 
 192     private static int countOccurrences(String value, char match) {
 193         int count = 0;
 194         for (char c : value.toCharArray()) {
 195             if (c == match) {
 196                ++count;
 197             }
 198         }
 199         return count;
 200     }
 201 }