1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.android.timezone.distro.tools;
17 
18 import com.android.i18n.timezone.TzDataSetVersion;
19 
20 import com.android.timezone.distro.DistroVersion;
21 import com.android.timezone.distro.TimeZoneDistro;
22 import com.android.timezone.distro.builder.TimeZoneDistroBuilder;
23 
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileOutputStream;
27 import java.io.IOException;
28 import java.io.InputStreamReader;
29 import java.io.OutputStream;
30 import java.io.Reader;
31 import java.util.Properties;
32 
33 /**
34  * A command-line tool for creating a time zone update distro and associated
35  * files.
36  *
37  * <p>Args:
38  * <dl>
39  *     <dt>input properties file</dt>
40  *     <dd>the file describing the distro and output dirs</dd>
41  * </dl>
42  *
43  * <p>The input properties file must have the entries:
44  * <dl>
45  *     <dt>rules.version</dt>
46  *     <dd>The IANA rules version.</dd>
47  *     <dt>revision</dt>
48  *     <dd>The distro revision (typically 1).</dd>
49  *     <dt>tzdata.file</dt>
50  *     <dd>The location of the tzdata file.</dd>
51  *     <dt>icu.file</dt>
52  *     <dd>The location of the ICU overlay .dat file.</dd>
53  *     <dt>tzlookup.file</dt>
54  *     <dd>The location of the tzlookup.xml file.</dd>
55  *     <dt>telephonylookup.file</dt>
56  *     <dd>The location of the telephonylookup.xml file.</dd>
57  *     <dt>output.distro.dir</dt>
58  *     <dd>The directory to write the distro.zip file to.</dd>
59  *     <dt>output.version.file</dt>
60  *     <dd>The location to write the version file to.</dd>
61  * </dl>
62  *
63  * <p>The output consists of:
64  * <ul>
65  *     <li>A distro .zip containing the input files. See
66  *     {@link com.android.timezone.distro.TimeZoneDistro}</li>
67  *     <li>A version file (same as contained in the distro .zip).</li>
68  * </ul>
69  */
70 public class CreateTimeZoneDistro {
71 
CreateTimeZoneDistro()72     private CreateTimeZoneDistro() {}
73 
main(String[] args)74     public static void main(String[] args) throws Exception {
75         if (args.length != 1) {
76             printUsage();
77             System.exit(1);
78         }
79         File f = new File(args[0]);
80         if (!f.exists()) {
81             System.err.println("Properties file " + f + " not found");
82             printUsage();
83             System.exit(2);
84         }
85         Properties properties = loadProperties(f);
86         String ianaRulesVersion = getMandatoryProperty(properties, "rules.version");
87         int revision = Integer.parseInt(getMandatoryProperty(properties, "revision"));
88 
89         // Create an object to hold version metadata for the tz data.
90         TzDataSetVersion tzDataSetVersion = new TzDataSetVersion(
91                 TzDataSetVersion.currentFormatMajorVersion(),
92                 TzDataSetVersion.currentFormatMinorVersion(),
93                 ianaRulesVersion,
94                 revision);
95         byte[] tzDataSetVersionBytes = tzDataSetVersion.toBytes();
96 
97         // Create a DistroVersion from the TzDataSetVersion.
98         DistroVersion distroVersion = new DistroVersion(
99                 tzDataSetVersion.getFormatMajorVersion(),
100                 tzDataSetVersion.getFormatMinorVersion(),
101                 tzDataSetVersion.getRulesVersion(),
102                 tzDataSetVersion.getRevision());
103         TimeZoneDistroBuilder builder = new TimeZoneDistroBuilder()
104                 .setDistroVersion(distroVersion)
105                 .setTzDataFile(getMandatoryPropertyFile(properties, "tzdata.file"))
106                 .setIcuDataFile(getMandatoryPropertyFile(properties, "icu.file"))
107                 .setTzLookupFile(getMandatoryPropertyFile(properties, "tzlookup.file"))
108                 .setTelephonyLookupFile(
109                         getMandatoryPropertyFile(properties, "telephonylookup.file"));
110         byte[] distroBytes = builder.buildBytes();
111 
112         File outputDistroDir = getMandatoryPropertyFile(properties, "output.distro.dir");
113         File outputVersionFile = new File(getMandatoryProperty(properties, "output.version.file"));
114 
115         // Write the tz data set version file.
116         try (OutputStream os = new FileOutputStream(outputVersionFile)) {
117             os.write(tzDataSetVersionBytes);
118         }
119         System.out.println("Wrote " + outputVersionFile);
120 
121         // Write the distro file.
122         File outputDistroFile = new File(outputDistroDir, TimeZoneDistro.FILE_NAME);
123         try (OutputStream os = new FileOutputStream(outputDistroFile)) {
124             os.write(distroBytes);
125         }
126         System.out.println("Wrote " + outputDistroFile);
127     }
128 
getMandatoryPropertyFile(Properties p, String propertyName)129     private static File getMandatoryPropertyFile(Properties p, String propertyName) {
130         String fileName = getMandatoryProperty(p, propertyName);
131         File file = new File(fileName);
132         if (!file.exists()) {
133             System.out.println(
134                     "Missing file: " + file + " for property " + propertyName + " does not exist.");
135             printUsage();
136             System.exit(4);
137         }
138         return file;
139     }
140 
getMandatoryProperty(Properties p, String propertyName)141     private static String getMandatoryProperty(Properties p, String propertyName) {
142         String value = p.getProperty(propertyName);
143         if (value == null) {
144             System.out.println("Missing property: " + propertyName);
145             printUsage();
146             System.exit(3);
147         }
148         return value;
149     }
150 
loadProperties(File f)151     private static Properties loadProperties(File f) throws IOException {
152         Properties p = new Properties();
153         try (Reader reader = new InputStreamReader(new FileInputStream(f))) {
154             p.load(reader);
155         }
156         return p;
157     }
158 
printUsage()159     private static void printUsage() {
160         System.out.println("Usage:");
161         System.out.println("\t" + CreateTimeZoneDistro.class.getName() +
162                 " <tzupdate.properties file>");
163     }
164 }
165