191c98d778c80e53a7f458264233375f982dcae14Neil Fuller/* 291c98d778c80e53a7f458264233375f982dcae14Neil Fuller * Copyright (C) 2015 The Android Open Source Project 391c98d778c80e53a7f458264233375f982dcae14Neil Fuller * 491c98d778c80e53a7f458264233375f982dcae14Neil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 591c98d778c80e53a7f458264233375f982dcae14Neil Fuller * you may not use this file except in compliance with the License. 691c98d778c80e53a7f458264233375f982dcae14Neil Fuller * You may obtain a copy of the License at 791c98d778c80e53a7f458264233375f982dcae14Neil Fuller * 891c98d778c80e53a7f458264233375f982dcae14Neil Fuller * http://www.apache.org/licenses/LICENSE-2.0 991c98d778c80e53a7f458264233375f982dcae14Neil Fuller * 1091c98d778c80e53a7f458264233375f982dcae14Neil Fuller * Unless required by applicable law or agreed to in writing, software 1191c98d778c80e53a7f458264233375f982dcae14Neil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 1291c98d778c80e53a7f458264233375f982dcae14Neil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1391c98d778c80e53a7f458264233375f982dcae14Neil Fuller * See the License for the specific language governing permissions and 1491c98d778c80e53a7f458264233375f982dcae14Neil Fuller * limitations under the License. 1591c98d778c80e53a7f458264233375f982dcae14Neil Fuller */ 1691c98d778c80e53a7f458264233375f982dcae14Neil Fullerpackage libcore.tzdata.update.tools; 1791c98d778c80e53a7f458264233375f982dcae14Neil Fuller 1891c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport java.io.ByteArrayOutputStream; 1991c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport java.io.File; 2091c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport java.io.FileInputStream; 2191c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport java.io.IOException; 2291c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport java.nio.charset.StandardCharsets; 2391c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport java.util.zip.ZipEntry; 2491c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport java.util.zip.ZipOutputStream; 2591c98d778c80e53a7f458264233375f982dcae14Neil Fullerimport libcore.tzdata.update.ConfigBundle; 2691c98d778c80e53a7f458264233375f982dcae14Neil Fuller 2791c98d778c80e53a7f458264233375f982dcae14Neil Fuller/** 2891c98d778c80e53a7f458264233375f982dcae14Neil Fuller * A class for creating a {@link ConfigBundle} containing timezone update data. 2991c98d778c80e53a7f458264233375f982dcae14Neil Fuller */ 3091c98d778c80e53a7f458264233375f982dcae14Neil Fullerpublic final class TzDataBundleBuilder { 3191c98d778c80e53a7f458264233375f982dcae14Neil Fuller 3291c98d778c80e53a7f458264233375f982dcae14Neil Fuller private String tzDataVersion; 3391c98d778c80e53a7f458264233375f982dcae14Neil Fuller private StringBuilder checksumsFileContent = new StringBuilder(); 3491c98d778c80e53a7f458264233375f982dcae14Neil Fuller private File zoneInfoFile; 3591c98d778c80e53a7f458264233375f982dcae14Neil Fuller private File icuTzDataFile; 3691c98d778c80e53a7f458264233375f982dcae14Neil Fuller 3791c98d778c80e53a7f458264233375f982dcae14Neil Fuller public TzDataBundleBuilder setTzDataVersion(String tzDataVersion) { 3891c98d778c80e53a7f458264233375f982dcae14Neil Fuller this.tzDataVersion = tzDataVersion; 3991c98d778c80e53a7f458264233375f982dcae14Neil Fuller return this; 4091c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 4191c98d778c80e53a7f458264233375f982dcae14Neil Fuller 4291c98d778c80e53a7f458264233375f982dcae14Neil Fuller public TzDataBundleBuilder addChecksum(String fileName, long checksum) { 4391c98d778c80e53a7f458264233375f982dcae14Neil Fuller checksumsFileContent.append(Long.toString(checksum)) 4491c98d778c80e53a7f458264233375f982dcae14Neil Fuller .append(',') 4591c98d778c80e53a7f458264233375f982dcae14Neil Fuller .append(fileName) 4691c98d778c80e53a7f458264233375f982dcae14Neil Fuller .append('\n'); 4791c98d778c80e53a7f458264233375f982dcae14Neil Fuller return this; 4891c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 4991c98d778c80e53a7f458264233375f982dcae14Neil Fuller 5091c98d778c80e53a7f458264233375f982dcae14Neil Fuller public TzDataBundleBuilder addBionicTzData(File zoneInfoFile) { 5191c98d778c80e53a7f458264233375f982dcae14Neil Fuller this.zoneInfoFile = zoneInfoFile; 5291c98d778c80e53a7f458264233375f982dcae14Neil Fuller return this; 5391c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 5491c98d778c80e53a7f458264233375f982dcae14Neil Fuller 5591c98d778c80e53a7f458264233375f982dcae14Neil Fuller public TzDataBundleBuilder addIcuTzData(File icuTzDataFile) { 5691c98d778c80e53a7f458264233375f982dcae14Neil Fuller this.icuTzDataFile = icuTzDataFile; 5791c98d778c80e53a7f458264233375f982dcae14Neil Fuller return this; 5891c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 5991c98d778c80e53a7f458264233375f982dcae14Neil Fuller 6091c98d778c80e53a7f458264233375f982dcae14Neil Fuller /** 6191c98d778c80e53a7f458264233375f982dcae14Neil Fuller * Builds a {@link libcore.tzdata.update.ConfigBundle}. 6291c98d778c80e53a7f458264233375f982dcae14Neil Fuller */ 6391c98d778c80e53a7f458264233375f982dcae14Neil Fuller public ConfigBundle build() throws IOException { 6491c98d778c80e53a7f458264233375f982dcae14Neil Fuller if (tzDataVersion == null) { 6591c98d778c80e53a7f458264233375f982dcae14Neil Fuller throw new IllegalStateException("Missing tzDataVersion"); 6691c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 6791c98d778c80e53a7f458264233375f982dcae14Neil Fuller if (zoneInfoFile == null) { 6891c98d778c80e53a7f458264233375f982dcae14Neil Fuller throw new IllegalStateException("Missing zoneInfo file"); 6991c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 7091c98d778c80e53a7f458264233375f982dcae14Neil Fuller 7191c98d778c80e53a7f458264233375f982dcae14Neil Fuller return buildUnvalidated(); 7291c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 7391c98d778c80e53a7f458264233375f982dcae14Neil Fuller 7491c98d778c80e53a7f458264233375f982dcae14Neil Fuller // For use in tests. 7591c98d778c80e53a7f458264233375f982dcae14Neil Fuller public TzDataBundleBuilder clearChecksumEntries() { 7691c98d778c80e53a7f458264233375f982dcae14Neil Fuller checksumsFileContent.setLength(0); 7791c98d778c80e53a7f458264233375f982dcae14Neil Fuller return this; 7891c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 7991c98d778c80e53a7f458264233375f982dcae14Neil Fuller 8091c98d778c80e53a7f458264233375f982dcae14Neil Fuller // For use in tests. 8191c98d778c80e53a7f458264233375f982dcae14Neil Fuller public TzDataBundleBuilder clearBionicTzData() { 8291c98d778c80e53a7f458264233375f982dcae14Neil Fuller this.zoneInfoFile = null; 8391c98d778c80e53a7f458264233375f982dcae14Neil Fuller return this; 8491c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 8591c98d778c80e53a7f458264233375f982dcae14Neil Fuller 8691c98d778c80e53a7f458264233375f982dcae14Neil Fuller /** 8791c98d778c80e53a7f458264233375f982dcae14Neil Fuller * For use in tests. Use {@link #build()}. 8891c98d778c80e53a7f458264233375f982dcae14Neil Fuller */ 8991c98d778c80e53a7f458264233375f982dcae14Neil Fuller public ConfigBundle buildUnvalidated() throws IOException { 9091c98d778c80e53a7f458264233375f982dcae14Neil Fuller ByteArrayOutputStream baos = new ByteArrayOutputStream(); 9191c98d778c80e53a7f458264233375f982dcae14Neil Fuller try (ZipOutputStream zos = new ZipOutputStream(baos)) { 9291c98d778c80e53a7f458264233375f982dcae14Neil Fuller addZipEntry(zos, ConfigBundle.CHECKSUMS_FILE_NAME, 9391c98d778c80e53a7f458264233375f982dcae14Neil Fuller checksumsFileContent.toString().getBytes(StandardCharsets.UTF_8)); 9491c98d778c80e53a7f458264233375f982dcae14Neil Fuller if (tzDataVersion != null) { 9591c98d778c80e53a7f458264233375f982dcae14Neil Fuller addZipEntry(zos, ConfigBundle.TZ_DATA_VERSION_FILE_NAME, 9691c98d778c80e53a7f458264233375f982dcae14Neil Fuller tzDataVersion.getBytes(StandardCharsets.UTF_8)); 9791c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 9891c98d778c80e53a7f458264233375f982dcae14Neil Fuller if (zoneInfoFile != null) { 9991c98d778c80e53a7f458264233375f982dcae14Neil Fuller addZipEntry(zos, ConfigBundle.ZONEINFO_FILE_NAME, 10091c98d778c80e53a7f458264233375f982dcae14Neil Fuller readFileAsByteArray(zoneInfoFile)); 10191c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 10291c98d778c80e53a7f458264233375f982dcae14Neil Fuller if (icuTzDataFile != null) { 10391c98d778c80e53a7f458264233375f982dcae14Neil Fuller addZipEntry(zos, ConfigBundle.ICU_DATA_FILE_NAME, 10491c98d778c80e53a7f458264233375f982dcae14Neil Fuller readFileAsByteArray(icuTzDataFile)); 10591c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 10691c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 10791c98d778c80e53a7f458264233375f982dcae14Neil Fuller return new ConfigBundle(baos.toByteArray()); 10891c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 10991c98d778c80e53a7f458264233375f982dcae14Neil Fuller 11091c98d778c80e53a7f458264233375f982dcae14Neil Fuller private static void addZipEntry(ZipOutputStream zos, String name, byte[] content) 11191c98d778c80e53a7f458264233375f982dcae14Neil Fuller throws IOException { 11291c98d778c80e53a7f458264233375f982dcae14Neil Fuller ZipEntry zipEntry = new ZipEntry(name); 11391c98d778c80e53a7f458264233375f982dcae14Neil Fuller zipEntry.setSize(content.length); 11491c98d778c80e53a7f458264233375f982dcae14Neil Fuller zos.putNextEntry(zipEntry); 11591c98d778c80e53a7f458264233375f982dcae14Neil Fuller zos.write(content); 11691c98d778c80e53a7f458264233375f982dcae14Neil Fuller zos.closeEntry(); 11791c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 11891c98d778c80e53a7f458264233375f982dcae14Neil Fuller 11991c98d778c80e53a7f458264233375f982dcae14Neil Fuller /** 12091c98d778c80e53a7f458264233375f982dcae14Neil Fuller * Returns the contents of 'path' as a byte array. 12191c98d778c80e53a7f458264233375f982dcae14Neil Fuller */ 12291c98d778c80e53a7f458264233375f982dcae14Neil Fuller public static byte[] readFileAsByteArray(File file) throws IOException { 12391c98d778c80e53a7f458264233375f982dcae14Neil Fuller byte[] buffer = new byte[8192]; 12491c98d778c80e53a7f458264233375f982dcae14Neil Fuller ByteArrayOutputStream baos = new ByteArrayOutputStream(); 12591c98d778c80e53a7f458264233375f982dcae14Neil Fuller try (FileInputStream fis = new FileInputStream(file)) { 12691c98d778c80e53a7f458264233375f982dcae14Neil Fuller int count; 12791c98d778c80e53a7f458264233375f982dcae14Neil Fuller while ((count = fis.read(buffer)) != -1) { 12891c98d778c80e53a7f458264233375f982dcae14Neil Fuller baos.write(buffer, 0, count); 12991c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 13091c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 13191c98d778c80e53a7f458264233375f982dcae14Neil Fuller return baos.toByteArray(); 13291c98d778c80e53a7f458264233375f982dcae14Neil Fuller } 13391c98d778c80e53a7f458264233375f982dcae14Neil Fuller} 13491c98d778c80e53a7f458264233375f982dcae14Neil Fuller 135