1 /*
   2  * Copyright (c) 2000, 2013, 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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 import java.util.ArrayList;
  27 import java.util.List;
  28 
  29 /**
  30  * Main class for the javazic time zone data compiler.
  31  *
  32  * @since 1.4
  33  */
  34 public class Main {
  35 
  36     private static boolean verbose = false;
  37     static boolean outputDoc = false;
  38 
  39     private List<String> ziFiles = new ArrayList<String>();
  40     private static String zoneNamesFile = null;
  41     private static String versionName = "unknown";
  42     private static String outputDir = "zoneinfo";
  43     private static String mapFile = null;
  44 
  45     /**
  46      * Parses the specified arguments and sets up the variables.
  47      * @param argv the arguments
  48      */
  49     void processArgs(String[] argv) {
  50         for (int i = 0; i < argv.length; i++) {
  51             String arg = argv[i];
  52             if (arg.startsWith("-h")) {
  53                 usage();
  54                 System.exit(0);
  55             } else if (arg.equals("-d")) {
  56                 outputDir = argv[++i];
  57             } else if (arg.equals("-v")) {
  58                 verbose = true;
  59             } else if (arg.equals("-V")) {
  60                 versionName = argv[++i];
  61             } else if (arg.equals("-doc")) {
  62                 outputDoc = true;
  63             } else if (arg.equals("-map")) {
  64                 outputDoc = true;
  65                 mapFile = argv[++i];
  66             } else if (arg.equals("-f")) {
  67                 zoneNamesFile = argv[++i];
  68             } else if (arg.equals("-S")) {
  69                 try {
  70                     Zoneinfo.setYear(Integer.parseInt(argv[++i]));
  71                 } catch (Exception e) {
  72                     error("invalid year: " + argv[i]);
  73                     usage();
  74                     System.exit(1);
  75                 }
  76             } else {
  77                 boolean isStartYear = arg.equals("-s");
  78                 if (isStartYear || arg.equals("-e")) {
  79                     try {
  80                         int year = Integer.parseInt(argv[++i]);
  81                         if (isStartYear) {
  82                             Zoneinfo.setStartYear(year);
  83                         } else {
  84                             Zoneinfo.setEndYear(year);
  85                         }
  86                     } catch (Exception e) {
  87                         error("invalid year: " + argv[i]);
  88                         usage();
  89                         System.exit(1);
  90                     }
  91                 } else {
  92                     // the rest of args are zoneinfo source files
  93                     while (i < argv.length) {
  94                         ziFiles.add(argv[i++]);
  95                     }
  96                 }
  97             }
  98         }
  99     }
 100 
 101     /**
 102      * Parses zoneinfo source files
 103      */
 104     int compile() {
 105         int nFiles = ziFiles.size();
 106         int status = 0;
 107         Mappings maps = new Mappings();
 108         BackEnd backend = BackEnd.getBackEnd();
 109 
 110         for (int i = 0; i < nFiles; i++) {
 111             Zoneinfo frontend = Zoneinfo.parse(ziFiles.get(i));
 112 
 113             for (String key : frontend.getZones().keySet()) {
 114                 info(key);
 115 
 116                 Timezone tz = frontend.phase2(key);
 117                 status |= backend.processZoneinfo(tz);
 118             }
 119 
 120             maps.add(frontend);
 121         }
 122 
 123         // special code for dealing with the conflicting name "MET"
 124         Zone.addMET();
 125 
 126         maps.resolve();
 127 
 128         status |= backend.generateSrc(maps);
 129 
 130         return status;
 131     }
 132 
 133     public static void main(String[] argv) {
 134         Main zic = new Main();
 135 
 136         /*
 137          * Parse args
 138          */
 139         zic.processArgs(argv);
 140 
 141         /*
 142          * Read target zone names
 143          */
 144         if (zoneNamesFile != null) {
 145             Zone.readZoneNames(zoneNamesFile);
 146         }
 147 
 148         zic.compile();
 149     }
 150 
 151     void usage() {
 152         System.err.println("Usage: javazic [options] file...\n"+
 153                            "         -f namefile  file containing zone names\n"+
 154                            "                      to be generated (ie, generating subset)\n"+
 155                            "         -d dir       output directory\n"+
 156                            "         -v           verbose\n"+
 157                            "         -V datavers  specifies the tzdata version string\n"+
 158                            "                      (eg, \"tzdata2000g\")"+
 159                            "         -S year      output only SimleTimeZone data of that year\n"+
 160                            "         -s year      start year (default: 1900)\n"+
 161                            "         -e year      end year (default: 2037)\n"+
 162                            "         -doc         generates HTML documents\n"+
 163                            "         -map mapfile generates HTML documents with map information\n"+
 164                            "         file...      zoneinfo source file(s)");
 165     }
 166 
 167     /**
 168      * @return the output directory path name
 169      */
 170     static String getOutputDir() {
 171         return outputDir;
 172     }
 173 
 174     /**
 175      * @return the map file's path and name
 176      */
 177     static String getMapFile() {
 178         return mapFile;
 179     }
 180 
 181     /**
 182      * Returns the time zone data version string specified by the -V
 183      * option. If it is not specified, "unknown" is returned.
 184      * @return the time zone data version string
 185      */
 186     static String getVersionName() {
 187         return versionName;
 188     }
 189 
 190     /**
 191      * Prints out the specified fatal error message and calls {@link
 192      * java.lang.System#exit System.exit(1)}.
 193      * @param msg the fatal error message
 194      */
 195     static void panic(String msg) {
 196         printMessage("fatal error", msg);
 197         System.exit(1);
 198     }
 199 
 200     /**
 201      * Prints out the specified error message.
 202      * @param msg the error message
 203      */
 204     static void error(String msg) {
 205         printMessage("error", msg);
 206     }
 207 
 208     /**
 209      * Prints out the specified warning message.
 210      * @param msg the warning message
 211      */
 212     static void warning(String msg) {
 213         printMessage("warning", msg);
 214     }
 215 
 216     /**
 217      * Prints out the informative message.
 218      * @param msg the informative message
 219      */
 220     static void info(String msg) {
 221         if (verbose) {
 222             printMessage(null, msg);
 223         }
 224     }
 225 
 226     private static void printMessage(String type, String msg) {
 227         if (type != null) {
 228             type += ": ";
 229         } else {
 230             type = "";
 231         }
 232         System.err.println("javazic: " + type + msg);
 233     }
 234 }