Path: blob/master/test/jdk/sun/util/calendar/zi/Gen.java
41153 views
/*1* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.IOException;24import java.io.File;25import java.io.FileOutputStream;26import java.io.DataOutputStream;27import java.io.RandomAccessFile;28import java.util.List;29import java.util.Map;30import java.util.Set;3132/**33* <code>Gen</code> is one of back-end classes of javazic, and generates34* ZoneInfoMappings and zone-specific file for each zone.35*/36class Gen extends BackEnd {3738/**39* Generates datafile in binary TLV format for each time zone.40* Regarding contents of output files, see {@link ZoneInfoFile}.41*42* @param Timezone43* @return 0 if no errors, or 1 if error occurred.44*/45int processZoneinfo(Timezone tz) {46try {47int size;48String outputDir = Main.getOutputDir();49String zonefile = ZoneInfoFile.getFileName(tz.getName());5051/* If outputDir doesn't end with file-separator, adds it. */52if (!outputDir.endsWith(File.separator)) {53outputDir += File.separatorChar;54}5556/* If zonefile includes file-separator, it's treated as part of57* pathname. And make directory if necessary.58*/59int index = zonefile.lastIndexOf(File.separatorChar);60if (index != -1) {61outputDir += zonefile.substring(0, index+1);62}63File outD = new File(outputDir);64outD.mkdirs();6566FileOutputStream fos =67new FileOutputStream(outputDir + zonefile.substring(index+1));68DataOutputStream dos = new DataOutputStream(fos);6970/* Output Label */71dos.write(ZoneInfoFile.JAVAZI_LABEL, 0,72ZoneInfoFile.JAVAZI_LABEL.length);7374/* Output Version of ZoneInfoFile */75dos.writeByte(ZoneInfoFile.JAVAZI_VERSION);7677List<Long> transitions = tz.getTransitions();78if (transitions != null) {79List<Integer> dstOffsets = tz.getDstOffsets();80List<Integer> offsets = tz.getOffsets();8182if ((dstOffsets == null && offsets != null) ||83(dstOffsets != null && offsets == null)) {84Main.panic("Data not exist. (dstOffsets or offsets)");85return 1;86}8788/* Output Transition records */89dos.writeByte(ZoneInfoFile.TAG_Transition);90size = transitions.size();91dos.writeShort((size * 8) & 0xFFFF);92int dstoffset;93for (int i = 0; i < size; i++) {94/* if DST offset is 0, this means DST isn't used.95* (NOT: offset's index is 0.)96*/97if ((dstoffset = dstOffsets.get(i).intValue()) == -1) {98dstoffset = 0;99}100101dos.writeLong((transitions.get(i).longValue() << 12)102| (dstoffset << 4)103| offsets.get(i).intValue());104105}106107/* Output data for GMTOffset */108List<Integer> gmtoffset = tz.getGmtOffsets();109dos.writeByte(ZoneInfoFile.TAG_Offset);110size = gmtoffset.size();111dos.writeShort((size * 4) & 0xFFFF);112for (int i = 0; i < size; i++) {113dos.writeInt(gmtoffset.get(i));114}115}116117/* Output data for SimpleTimeZone */118List<RuleRec> stz = tz.getLastRules();119if (stz != null) {120RuleRec[] rr = new RuleRec[2];121boolean wall = true;122123rr[0] = stz.get(0);124rr[1] = stz.get(1);125126dos.writeByte(ZoneInfoFile.TAG_SimpleTimeZone);127wall = rr[0].getTime().isWall() && rr[1].getTime().isWall();128if (wall) {129dos.writeShort(32);130} else {131dos.writeShort(40);132}133134for (int i = 0; i < 2; i++) {135dos.writeInt(rr[i].getMonthNum() - 1); // 0-based month number136dos.writeInt(rr[i].getDay().getDayForSimpleTimeZone());137dos.writeInt(rr[i].getDay().getDayOfWeekForSimpleTimeZoneInt());138dos.writeInt((int)rr[i].getTime().getTime());139if (!wall) {140dos.writeInt((rr[i].getTime().getType() & 0xFF) - 1);141}142}143}144145/* Output RawOffset */146dos.writeByte(ZoneInfoFile.TAG_RawOffset);147dos.writeShort(4);148dos.writeInt(tz.getRawOffset());149150/* Output willGMTOffsetChange flag */151if (tz.willGMTOffsetChange()) {152dos.writeByte(ZoneInfoFile.TAG_GMTOffsetWillChange);153dos.writeShort(1);154dos.writeByte(1);155}156157/* Output LastDSTSaving */158dos.writeByte(ZoneInfoFile.TAG_LastDSTSaving);159dos.writeShort(2);160dos.writeShort(tz.getLastDSTSaving()/1000);161162/* Output checksum */163dos.writeByte(ZoneInfoFile.TAG_CRC32);164dos.writeShort(4);165dos.writeInt(tz.getCRC32());166167fos.close();168dos.close();169} catch(IOException e) {170Main.panic("IO error: "+e.getMessage());171return 1;172}173174return 0;175}176177/**178* Generates ZoneInfoMappings in binary TLV format for each zone.179* Regarding contents of output files, see {@link ZoneInfoFile}.180*181* @param Mappings182* @return 0 if no errors, or 1 if error occurred.183*/184int generateSrc(Mappings map) {185try {186int index;187int block_size;188int roi_size;189long fp;190String outputDir = Main.getOutputDir();191192/* If outputDir doesn't end with file-separator, adds it. */193if (!outputDir.endsWith(File.separator)) {194outputDir += File.separatorChar;195}196197File outD = new File(outputDir);198outD.mkdirs();199200/* Open ZoneInfoMapping file to write. */201RandomAccessFile raf =202new RandomAccessFile(outputDir + ZoneInfoFile.JAVAZM_FILE_NAME, "rw");203204/* Whether rawOffsetIndex list exists or not. */205List<Integer> roi = map.getRawOffsetsIndex();206if (roi == null) {207Main.panic("Data not exist. (rawOffsetsIndex)");208return 1;209}210roi_size = roi.size();211212/* Whether rawOffsetIndexTable list exists or not. */213List<Set<String>> roit = map.getRawOffsetsIndexTable();214if (roit == null || roit.size() != roi_size) {215Main.panic("Data not exist. (rawOffsetsIndexTable) Otherwise, Invalid size");216return 1;217}218219/* Output Label */220raf.write(ZoneInfoFile.JAVAZM_LABEL, 0,221ZoneInfoFile.JAVAZM_LABEL.length);222223/* Output Version */224raf.writeByte(ZoneInfoFile.JAVAZM_VERSION);225226index = ZoneInfoFile.JAVAZM_LABEL.length + 2;227228/* Output Version of Olson's tzdata */229byte[] b = Main.getVersionName().getBytes("UTF-8");230raf.writeByte(ZoneInfoFile.TAG_TZDataVersion);231raf.writeShort((b.length+1) & 0xFFFF);232raf.write(b);233raf.writeByte(0x00);234index += b.length + 4;235236/* Output ID list. */237raf.writeByte(ZoneInfoFile.TAG_ZoneIDs);238block_size = 2;239raf.writeShort(block_size & 0xFFFF);240short nID = 0;241raf.writeShort(nID & 0xFFFF);242for (int i = 0; i < roi_size; i++) {243for (String key : roit.get(i)) {244byte size = (byte)key.getBytes("UTF-8").length;245raf.writeByte(size & 0xFF);246raf.write(key.getBytes("UTF-8"), 0, size);247block_size += 1 + size;248nID++;249}250}251fp = raf.getFilePointer();252raf.seek(index);253raf.writeShort((block_size) & 0xFFFF);254raf.writeShort(nID & 0xFFFF);255raf.seek(fp);256257/* Output sorted rawOffset list. */258raf.writeByte(ZoneInfoFile.TAG_RawOffsets);259index += 3 + block_size;260block_size = roi_size * 4;261raf.writeShort(block_size & 0xFFFF);262for (int i = 0; i < roi_size; i++) {263raf.writeInt(Integer.parseInt(roi.get(i).toString()));264}265266/* Output sorted rawOffsetIndex list. */267raf.writeByte(ZoneInfoFile.TAG_RawOffsetIndices);268index += 3 + block_size;269block_size = 0;270raf.writeShort(block_size & 0xFFFF);271int num;272for (int i = 0; i < roi_size; i++) {273num = roit.get(i).size();274block_size += num;275for (int j = 0; j < num; j++) {276raf.writeByte(i);277}278}279fp = raf.getFilePointer();280raf.seek(index);281raf.writeShort((block_size) & 0xFFFF);282raf.seek(fp);283284/* Whether alias list exists or not. */285Map<String,String> a = map.getAliases();286if (a == null) {287Main.panic("Data not exist. (aliases)");288return 0;289}290291/* Output ID list. */292raf.writeByte(ZoneInfoFile.TAG_ZoneAliases);293index += 3 + block_size;294block_size = 2;295raf.writeShort(block_size & 0xFFFF);296raf.writeShort(a.size() & 0xFFFF);297for (String key : a.keySet()) {298String alias = a.get(key);299byte key_size = (byte)key.length();300byte alias_size = (byte)alias.length();301raf.writeByte(key_size & 0xFF);302raf.write(key.getBytes("UTF-8"), 0, key_size);303raf.writeByte(alias_size & 0xFF);304raf.write(alias.getBytes("UTF-8"), 0, alias_size);305block_size += 2 + key_size + alias_size;306}307fp = raf.getFilePointer();308raf.seek(index);309raf.writeShort((block_size) & 0xFFFF);310raf.seek(fp);311312/* Output the exclude list if it exists. */313List<String> excludedZones = map.getExcludeList();314if (excludedZones != null) {315raf.writeByte(ZoneInfoFile.TAG_ExcludedZones);316index += 3 + block_size;317block_size = 2;318raf.writeShort(block_size & 0xFFFF); // place holder319raf.writeShort(excludedZones.size()); // the number of excluded zones320for (String name : excludedZones) {321byte size = (byte) name.length();322raf.writeByte(size); // byte length323raf.write(name.getBytes("UTF-8"), 0, size); // zone name324block_size += 1 + size;325}326fp = raf.getFilePointer();327raf.seek(index);328raf.writeShort(block_size & 0xFFFF);329raf.seek(fp);330}331332/* Close ZoneInfoMapping file. */333raf.close();334} catch(IOException e) {335Main.panic("IO error: "+e.getMessage());336return 1;337}338339return 0;340}341}342343344