jdk/test/sun/util/calendar/zi/Gen.java
changeset 15658 55b829ca2334
child 23010 6dadb192ad81
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/util/calendar/zi/Gen.java	Tue Feb 12 09:25:43 2013 -0800
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import  java.io.IOException;
+import  java.io.File;
+import  java.io.FileOutputStream;
+import  java.io.DataOutputStream;
+import  java.io.RandomAccessFile;
+import  java.util.List;
+import  java.util.Map;
+import  java.util.Set;
+
+/**
+ * <code>Gen</code> is one of back-end classes of javazic, and generates
+ * ZoneInfoMappings and zone-specific file for each zone.
+ */
+class Gen extends BackEnd {
+
+    /**
+     * Generates datafile in binary TLV format for each time zone.
+     * Regarding contents of output files, see {@link ZoneInfoFile}.
+     *
+     * @param Timezone
+     * @return 0 if no errors, or 1 if error occurred.
+     */
+    int processZoneinfo(Timezone tz) {
+        try {
+            int size;
+            String outputDir = Main.getOutputDir();
+            String zonefile = ZoneInfoFile.getFileName(tz.getName());
+
+            /* If outputDir doesn't end with file-separator, adds it. */
+            if (!outputDir.endsWith(File.separator)) {
+                outputDir += File.separatorChar;
+            }
+
+            /* If zonefile includes file-separator, it's treated as part of
+             * pathname. And make directory if necessary.
+             */
+            int index = zonefile.lastIndexOf(File.separatorChar);
+            if (index != -1) {
+                outputDir += zonefile.substring(0, index+1);
+            }
+            File outD = new File(outputDir);
+            outD.mkdirs();
+
+            FileOutputStream fos =
+                new FileOutputStream(outputDir + zonefile.substring(index+1));
+            DataOutputStream dos = new DataOutputStream(fos);
+
+            /* Output Label */
+            dos.write(ZoneInfoFile.JAVAZI_LABEL, 0,
+                      ZoneInfoFile.JAVAZI_LABEL.length);
+
+            /* Output Version of ZoneInfoFile */
+            dos.writeByte(ZoneInfoFile.JAVAZI_VERSION);
+
+            List<Long> transitions = tz.getTransitions();
+            if (transitions != null) {
+                List<Integer> dstOffsets = tz.getDstOffsets();
+                List<Integer> offsets = tz.getOffsets();
+
+                if ((dstOffsets == null && offsets != null) ||
+                    (dstOffsets != null && offsets == null)) {
+                    Main.panic("Data not exist. (dstOffsets or offsets)");
+                    return 1;
+                }
+
+                /* Output Transition records */
+                dos.writeByte(ZoneInfoFile.TAG_Transition);
+                size = transitions.size();
+                dos.writeShort((size * 8) & 0xFFFF);
+                int dstoffset;
+                for (int i = 0; i < size; i++) {
+                    /* if DST offset is 0, this means DST isn't used.
+                     * (NOT: offset's index is 0.)
+                     */
+                    if ((dstoffset = dstOffsets.get(i).intValue()) == -1) {
+                        dstoffset = 0;
+                    }
+
+                    dos.writeLong((transitions.get(i).longValue() << 12)
+                                  | (dstoffset << 4)
+                                  | offsets.get(i).intValue());
+
+                }
+
+                /* Output data for GMTOffset */
+                List<Integer> gmtoffset = tz.getGmtOffsets();
+                dos.writeByte(ZoneInfoFile.TAG_Offset);
+                size = gmtoffset.size();
+                dos.writeShort((size * 4) & 0xFFFF);
+                for (int i = 0; i < size; i++) {
+                    dos.writeInt(gmtoffset.get(i));
+                }
+            }
+
+            /* Output data for SimpleTimeZone */
+            List<RuleRec> stz = tz.getLastRules();
+            if (stz != null) {
+                RuleRec[] rr = new RuleRec[2];
+                boolean wall = true;
+
+                rr[0] = stz.get(0);
+                rr[1] = stz.get(1);
+
+                dos.writeByte(ZoneInfoFile.TAG_SimpleTimeZone);
+                wall = rr[0].getTime().isWall() && rr[1].getTime().isWall();
+                if (wall) {
+                    dos.writeShort(32);
+                } else {
+                    dos.writeShort(40);
+                }
+
+                for (int i = 0; i < 2; i++) {
+                    dos.writeInt(rr[i].getMonthNum() - 1); // 0-based month number
+                    dos.writeInt(rr[i].getDay().getDayForSimpleTimeZone());
+                    dos.writeInt(rr[i].getDay().getDayOfWeekForSimpleTimeZoneInt());
+                    dos.writeInt((int)rr[i].getTime().getTime());
+                    if (!wall) {
+                        dos.writeInt((rr[i].getTime().getType() & 0xFF) - 1);
+                    }
+                }
+            }
+
+            /* Output RawOffset */
+            dos.writeByte(ZoneInfoFile.TAG_RawOffset);
+            dos.writeShort(4);
+            dos.writeInt(tz.getRawOffset());
+
+            /* Output willGMTOffsetChange flag */
+            if (tz.willGMTOffsetChange()) {
+                dos.writeByte(ZoneInfoFile.TAG_GMTOffsetWillChange);
+                dos.writeShort(1);
+                dos.writeByte(1);
+            }
+
+            /* Output LastDSTSaving */
+            dos.writeByte(ZoneInfoFile.TAG_LastDSTSaving);
+            dos.writeShort(2);
+            dos.writeShort(tz.getLastDSTSaving()/1000);
+
+            /* Output checksum */
+            dos.writeByte(ZoneInfoFile.TAG_CRC32);
+            dos.writeShort(4);
+            dos.writeInt(tz.getCRC32());
+
+            fos.close();
+            dos.close();
+        } catch(IOException e) {
+            Main.panic("IO error: "+e.getMessage());
+            return 1;
+        }
+
+        return 0;
+    }
+
+    /**
+     * Generates ZoneInfoMappings in binary TLV format for each zone.
+     * Regarding contents of output files, see {@link ZoneInfoFile}.
+     *
+     * @param Mappings
+     * @return 0 if no errors, or 1 if error occurred.
+     */
+    int generateSrc(Mappings map) {
+        try {
+            int index;
+            int block_size;
+            int roi_size;
+            long fp;
+            String outputDir = Main.getOutputDir();
+
+            /* If outputDir doesn't end with file-separator, adds it. */
+            if (!outputDir.endsWith(File.separator)) {
+                outputDir += File.separatorChar;
+            }
+
+            File outD = new File(outputDir);
+            outD.mkdirs();
+
+            /* Open ZoneInfoMapping file to write. */
+            RandomAccessFile raf =
+                new RandomAccessFile(outputDir + ZoneInfoFile.JAVAZM_FILE_NAME, "rw");
+
+            /* Whether rawOffsetIndex list exists or not. */
+            List<Integer> roi = map.getRawOffsetsIndex();
+            if (roi == null) {
+                Main.panic("Data not exist. (rawOffsetsIndex)");
+                return 1;
+            }
+            roi_size = roi.size();
+
+            /* Whether rawOffsetIndexTable list exists or not. */
+            List<Set<String>> roit = map.getRawOffsetsIndexTable();
+            if (roit == null || roit.size() != roi_size) {
+                Main.panic("Data not exist. (rawOffsetsIndexTable) Otherwise, Invalid size");
+                return 1;
+            }
+
+            /* Output Label */
+            raf.write(ZoneInfoFile.JAVAZM_LABEL, 0,
+                      ZoneInfoFile.JAVAZM_LABEL.length);
+
+            /* Output Version */
+            raf.writeByte(ZoneInfoFile.JAVAZM_VERSION);
+
+            index = ZoneInfoFile.JAVAZM_LABEL.length + 2;
+
+            /* Output Version of Olson's tzdata */
+            byte[] b = Main.getVersionName().getBytes("UTF-8");
+            raf.writeByte(ZoneInfoFile.TAG_TZDataVersion);
+            raf.writeShort((b.length+1) & 0xFFFF);
+            raf.write(b);
+            raf.writeByte(0x00);
+            index += b.length + 4;
+
+            /* Output ID list. */
+            raf.writeByte(ZoneInfoFile.TAG_ZoneIDs);
+            block_size = 2;
+            raf.writeShort(block_size & 0xFFFF);
+            short nID = 0;
+            raf.writeShort(nID & 0xFFFF);
+            for (int i = 0; i < roi_size; i++) {
+                for (String key : roit.get(i)) {
+                    byte size = (byte)key.getBytes("UTF-8").length;
+                    raf.writeByte(size & 0xFF);
+                    raf.write(key.getBytes("UTF-8"), 0, size);
+                    block_size += 1 + size;
+                    nID++;
+                }
+            }
+            fp = raf.getFilePointer();
+            raf.seek(index);
+            raf.writeShort((block_size) & 0xFFFF);
+            raf.writeShort(nID & 0xFFFF);
+            raf.seek(fp);
+
+            /* Output sorted rawOffset list. */
+            raf.writeByte(ZoneInfoFile.TAG_RawOffsets);
+            index += 3 + block_size;
+            block_size = roi_size * 4;
+            raf.writeShort(block_size & 0xFFFF);
+            for (int i = 0; i < roi_size; i++) {
+                raf.writeInt(Integer.parseInt(roi.get(i).toString()));
+            }
+
+            /* Output sorted rawOffsetIndex list. */
+            raf.writeByte(ZoneInfoFile.TAG_RawOffsetIndices);
+            index += 3 + block_size;
+            block_size = 0;
+            raf.writeShort(block_size & 0xFFFF);
+            int num;
+            for (int i = 0; i < roi_size; i++) {
+                num = roit.get(i).size();
+                block_size += num;
+                for (int j = 0; j < num; j++) {
+                    raf.writeByte(i);
+                }
+            }
+            fp = raf.getFilePointer();
+            raf.seek(index);
+            raf.writeShort((block_size) & 0xFFFF);
+            raf.seek(fp);
+
+            /* Whether alias list exists or not. */
+            Map<String,String> a = map.getAliases();
+            if (a == null) {
+                Main.panic("Data not exist. (aliases)");
+                return 0;
+            }
+
+            /* Output ID list. */
+            raf.writeByte(ZoneInfoFile.TAG_ZoneAliases);
+            index += 3 + block_size;
+            block_size = 2;
+            raf.writeShort(block_size & 0xFFFF);
+            raf.writeShort(a.size() & 0xFFFF);
+            for (String key : a.keySet()) {
+                String alias = a.get(key);
+                byte key_size = (byte)key.length();
+                byte alias_size = (byte)alias.length();
+                raf.writeByte(key_size & 0xFF);
+                raf.write(key.getBytes("UTF-8"), 0, key_size);
+                raf.writeByte(alias_size & 0xFF);
+                raf.write(alias.getBytes("UTF-8"), 0, alias_size);
+                block_size += 2 + key_size + alias_size;
+            }
+            fp = raf.getFilePointer();
+            raf.seek(index);
+            raf.writeShort((block_size) & 0xFFFF);
+            raf.seek(fp);
+
+            /* Output the exclude list if it exists. */
+            List<String> excludedZones = map.getExcludeList();
+            if (excludedZones != null) {
+                raf.writeByte(ZoneInfoFile.TAG_ExcludedZones);
+                index += 3 + block_size;
+                block_size = 2;
+                raf.writeShort(block_size & 0xFFFF);  // place holder
+                raf.writeShort(excludedZones.size()); // the number of excluded zones
+                for (String name : excludedZones) {
+                    byte size = (byte) name.length();
+                    raf.writeByte(size);                 // byte length
+                    raf.write(name.getBytes("UTF-8"), 0, size); // zone name
+                    block_size += 1 + size;
+                }
+                fp = raf.getFilePointer();
+                raf.seek(index);
+                raf.writeShort(block_size & 0xFFFF);
+                raf.seek(fp);
+            }
+
+            /* Close ZoneInfoMapping file. */
+            raf.close();
+        } catch(IOException e) {
+            Main.panic("IO error: "+e.getMessage());
+            return 1;
+        }
+
+        return 0;
+    }
+}