1 /*
   2  * Copyright (c) 2007, 2012, 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[] s) throws Exception {
  31         for (int i = 0; i < s.length; i ++) {
  32             if ("-d".equals(s[i])) {
  33                 i++;
  34                 if (i == s.length) {
  35                     throw new RuntimeException("-d needs output file name");
  36                 } else {
  37                     dump(s[i]);
  38                 }
  39             } else if ("-c".equals(s[i])) {
  40                 if (i+2 == s.length) {
  41                     throw new RuntimeException("-d needs two file name arguments, before and after respectively");
  42                 } else {
  43                     compare(s[++i], s[++i]);
  44                 }
  45             }
  46         }
  47     }
  48 
  49     private static void dump(String outfile) {
  50         File f = new File(outfile);
  51         PrintWriter pw;
  52         try {
  53             f.createNewFile();
  54             pw = new PrintWriter(f);
  55         } catch (Exception fnfe) {
  56             throw new RuntimeException(fnfe);
  57         }
  58         for (char c1 = 'A'; c1 <= 'Z'; c1++) {
  59             for (char c2 = 'A'; c2 <= 'Z'; c2++) {
  60                 String ctry = new StringBuilder().append(c1).append(c2).toString();
  61                 try {
  62                     Currency c = Currency.getInstance(new Locale("", ctry));
  63                     if (c != null) {
  64                         pw.printf(Locale.ROOT, "%s=%s,%03d,%1d\n",
  65                             ctry,
  66                             c.getCurrencyCode(),
  67                             c.getNumericCode(),
  68                             c.getDefaultFractionDigits());
  69                     }
  70                 } catch (IllegalArgumentException iae) {
  71                     // invalid country code
  72                     continue;
  73                 }
  74             }
  75         }
  76         pw.flush();
  77         pw.close();
  78     }
  79 
  80     private static void compare(String beforeFile, String afterFile) throws Exception {
  81         // load file contents
  82         Properties before = new Properties();
  83         Properties after = new Properties();
  84         try {
  85             before.load(new FileReader(beforeFile));
  86             after.load(new FileReader(afterFile));
  87         } catch (IOException ioe) {
  88             throw new RuntimeException(ioe);
  89         }
  90 
  91         // remove the same contents from the 'after' properties
  92         Set<String> keys = before.stringPropertyNames();
  93         for (String key: keys) {
  94             String beforeVal = before.getProperty(key);
  95             String afterVal = after.getProperty(key);
  96             System.out.printf("Removing country: %s. before: %s, after: %s", key, beforeVal, afterVal);
  97             if (beforeVal.equals(afterVal)) {
  98                 after.remove(key);
  99                 System.out.printf(" --- removed\n");
 100             } else {
 101                 System.out.printf(" --- NOT removed\n");
 102             }
 103         }
 104 
 105         // now look at the currency.properties
 106         String propFileName = System.getProperty("java.home") + File.separator +
 107                               "lib" + File.separator + "currency.properties";
 108         Properties p = new Properties();
 109         try {
 110             p.load(new FileReader(propFileName));
 111         } catch (IOException ioe) {
 112             throw new RuntimeException(ioe);
 113         }
 114 
 115         // test each replacements
 116         keys = p.stringPropertyNames();
 117         Pattern propertiesPattern =
 118             Pattern.compile("([A-Z]{3})\\s*,\\s*(\\d{3})\\s*,\\s*" +
 119                 "([0-3])\\s*,?\\s*(\\d{4}-\\d{2}-\\d{2}T\\d{2}:" +
 120                 "\\d{2}:\\d{2})?");
 121         for (String key: keys) {
 122             String val = p.getProperty(key);
 123             try {
 124                 if (countOccurrences(val, ',') == 3 && !isPastCutoverDate(val)) {
 125                     System.out.println("Skipping since date is in future");
 126                     continue; // skip since date in future (no effect)
 127                 }
 128             } catch (ParseException pe) {
 129                 // swallow - currency class should not honour this value
 130                 continue;
 131             }
 132             String afterVal = after.getProperty(key);
 133             System.out.printf("Testing key: %s, val: %s... ", key, val);
 134             System.out.println("AfterVal is : " + afterVal);
 135 
 136             Matcher m = propertiesPattern.matcher(val.toUpperCase(Locale.ROOT));
 137             if (!m.find()) {
 138                 // format is not recognized.
 139                 System.out.printf("Format is not recognized.\n");
 140                 if (afterVal != null) {
 141                     throw new RuntimeException("Currency data replacement for "+key+" failed: It was incorrectly altered to "+afterVal);
 142                 }
 143 
 144                 // ignore this
 145                 continue;
 146             }
 147             Matcher mAfter = propertiesPattern.matcher(afterVal);
 148             mAfter.find();
 149 
 150             String code = m.group(1);
 151             String codeAfter = mAfter.group(1);
 152             int numeric = Integer.parseInt(m.group(2));
 153             int numericAfter = Integer.parseInt(mAfter.group(2));
 154             int fraction = Integer.parseInt(m.group(3));
 155             int fractionAfter = Integer.parseInt(mAfter.group(3));
 156             if (code.equals(codeAfter) &&
 157                 (numeric == numericAfter)&&
 158                 (fraction == fractionAfter)) {
 159                 after.remove(key);
 160             } else {
 161                 throw new RuntimeException("Currency data replacement for "+key+" failed: actual: (alphacode: "+codeAfter+", numcode: "+numericAfter+", fraction: "+fractionAfter+"), expected:  (alphacode: "+code+", numcode: "+numeric+", fraction: "+fraction+")");
 162             }
 163             System.out.printf("Success!\n");
 164         }
 165         if (!after.isEmpty()) {
 166             StringBuilder sb = new StringBuilder()
 167                 .append("Currency data replacement failed.  Unnecessary modification was(were) made for the following currencies:\n");
 168             keys = after.stringPropertyNames();
 169             for (String key : keys) {
 170                 sb.append("    country: ")
 171                 .append(key)
 172                 .append(" currency: ")
 173                 .append(after.getProperty(key))
 174                 .append("\n");
 175             }
 176             throw new RuntimeException(sb.toString());
 177         }
 178     }
 179 
 180     private static boolean isPastCutoverDate(String s)
 181             throws IndexOutOfBoundsException, NullPointerException, ParseException {
 182         String dateString = s.substring(s.lastIndexOf(',')+1, s.length()).trim();
 183         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.ROOT);
 184         format.setTimeZone(TimeZone.getTimeZone("GMT"));
 185         format.setLenient(false);
 186 
 187         long time = format.parse(dateString).getTime();
 188         if (System.currentTimeMillis() - time >= 0L) {
 189             return true;
 190         } else {
 191             return false;
 192         }
 193     }
 194 
 195     private static int countOccurrences(String value, char match) {
 196         int count = 0;
 197         for (char c : value.toCharArray()) {
 198             if (c == match) {
 199                ++count;
 200             }
 201         }
 202         return count;
 203     }
 204 }