jdk/test/sun/util/calendar/zi/Gen.java
changeset 15658 55b829ca2334
child 23010 6dadb192ad81
equal deleted inserted replaced
15657:c588664d547e 15658:55b829ca2334
       
     1 /*
       
     2  * Copyright (c) 2000, 2011, 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.io.IOException;
       
    27 import  java.io.File;
       
    28 import  java.io.FileOutputStream;
       
    29 import  java.io.DataOutputStream;
       
    30 import  java.io.RandomAccessFile;
       
    31 import  java.util.List;
       
    32 import  java.util.Map;
       
    33 import  java.util.Set;
       
    34 
       
    35 /**
       
    36  * <code>Gen</code> is one of back-end classes of javazic, and generates
       
    37  * ZoneInfoMappings and zone-specific file for each zone.
       
    38  */
       
    39 class Gen extends BackEnd {
       
    40 
       
    41     /**
       
    42      * Generates datafile in binary TLV format for each time zone.
       
    43      * Regarding contents of output files, see {@link ZoneInfoFile}.
       
    44      *
       
    45      * @param Timezone
       
    46      * @return 0 if no errors, or 1 if error occurred.
       
    47      */
       
    48     int processZoneinfo(Timezone tz) {
       
    49         try {
       
    50             int size;
       
    51             String outputDir = Main.getOutputDir();
       
    52             String zonefile = ZoneInfoFile.getFileName(tz.getName());
       
    53 
       
    54             /* If outputDir doesn't end with file-separator, adds it. */
       
    55             if (!outputDir.endsWith(File.separator)) {
       
    56                 outputDir += File.separatorChar;
       
    57             }
       
    58 
       
    59             /* If zonefile includes file-separator, it's treated as part of
       
    60              * pathname. And make directory if necessary.
       
    61              */
       
    62             int index = zonefile.lastIndexOf(File.separatorChar);
       
    63             if (index != -1) {
       
    64                 outputDir += zonefile.substring(0, index+1);
       
    65             }
       
    66             File outD = new File(outputDir);
       
    67             outD.mkdirs();
       
    68 
       
    69             FileOutputStream fos =
       
    70                 new FileOutputStream(outputDir + zonefile.substring(index+1));
       
    71             DataOutputStream dos = new DataOutputStream(fos);
       
    72 
       
    73             /* Output Label */
       
    74             dos.write(ZoneInfoFile.JAVAZI_LABEL, 0,
       
    75                       ZoneInfoFile.JAVAZI_LABEL.length);
       
    76 
       
    77             /* Output Version of ZoneInfoFile */
       
    78             dos.writeByte(ZoneInfoFile.JAVAZI_VERSION);
       
    79 
       
    80             List<Long> transitions = tz.getTransitions();
       
    81             if (transitions != null) {
       
    82                 List<Integer> dstOffsets = tz.getDstOffsets();
       
    83                 List<Integer> offsets = tz.getOffsets();
       
    84 
       
    85                 if ((dstOffsets == null && offsets != null) ||
       
    86                     (dstOffsets != null && offsets == null)) {
       
    87                     Main.panic("Data not exist. (dstOffsets or offsets)");
       
    88                     return 1;
       
    89                 }
       
    90 
       
    91                 /* Output Transition records */
       
    92                 dos.writeByte(ZoneInfoFile.TAG_Transition);
       
    93                 size = transitions.size();
       
    94                 dos.writeShort((size * 8) & 0xFFFF);
       
    95                 int dstoffset;
       
    96                 for (int i = 0; i < size; i++) {
       
    97                     /* if DST offset is 0, this means DST isn't used.
       
    98                      * (NOT: offset's index is 0.)
       
    99                      */
       
   100                     if ((dstoffset = dstOffsets.get(i).intValue()) == -1) {
       
   101                         dstoffset = 0;
       
   102                     }
       
   103 
       
   104                     dos.writeLong((transitions.get(i).longValue() << 12)
       
   105                                   | (dstoffset << 4)
       
   106                                   | offsets.get(i).intValue());
       
   107 
       
   108                 }
       
   109 
       
   110                 /* Output data for GMTOffset */
       
   111                 List<Integer> gmtoffset = tz.getGmtOffsets();
       
   112                 dos.writeByte(ZoneInfoFile.TAG_Offset);
       
   113                 size = gmtoffset.size();
       
   114                 dos.writeShort((size * 4) & 0xFFFF);
       
   115                 for (int i = 0; i < size; i++) {
       
   116                     dos.writeInt(gmtoffset.get(i));
       
   117                 }
       
   118             }
       
   119 
       
   120             /* Output data for SimpleTimeZone */
       
   121             List<RuleRec> stz = tz.getLastRules();
       
   122             if (stz != null) {
       
   123                 RuleRec[] rr = new RuleRec[2];
       
   124                 boolean wall = true;
       
   125 
       
   126                 rr[0] = stz.get(0);
       
   127                 rr[1] = stz.get(1);
       
   128 
       
   129                 dos.writeByte(ZoneInfoFile.TAG_SimpleTimeZone);
       
   130                 wall = rr[0].getTime().isWall() && rr[1].getTime().isWall();
       
   131                 if (wall) {
       
   132                     dos.writeShort(32);
       
   133                 } else {
       
   134                     dos.writeShort(40);
       
   135                 }
       
   136 
       
   137                 for (int i = 0; i < 2; i++) {
       
   138                     dos.writeInt(rr[i].getMonthNum() - 1); // 0-based month number
       
   139                     dos.writeInt(rr[i].getDay().getDayForSimpleTimeZone());
       
   140                     dos.writeInt(rr[i].getDay().getDayOfWeekForSimpleTimeZoneInt());
       
   141                     dos.writeInt((int)rr[i].getTime().getTime());
       
   142                     if (!wall) {
       
   143                         dos.writeInt((rr[i].getTime().getType() & 0xFF) - 1);
       
   144                     }
       
   145                 }
       
   146             }
       
   147 
       
   148             /* Output RawOffset */
       
   149             dos.writeByte(ZoneInfoFile.TAG_RawOffset);
       
   150             dos.writeShort(4);
       
   151             dos.writeInt(tz.getRawOffset());
       
   152 
       
   153             /* Output willGMTOffsetChange flag */
       
   154             if (tz.willGMTOffsetChange()) {
       
   155                 dos.writeByte(ZoneInfoFile.TAG_GMTOffsetWillChange);
       
   156                 dos.writeShort(1);
       
   157                 dos.writeByte(1);
       
   158             }
       
   159 
       
   160             /* Output LastDSTSaving */
       
   161             dos.writeByte(ZoneInfoFile.TAG_LastDSTSaving);
       
   162             dos.writeShort(2);
       
   163             dos.writeShort(tz.getLastDSTSaving()/1000);
       
   164 
       
   165             /* Output checksum */
       
   166             dos.writeByte(ZoneInfoFile.TAG_CRC32);
       
   167             dos.writeShort(4);
       
   168             dos.writeInt(tz.getCRC32());
       
   169 
       
   170             fos.close();
       
   171             dos.close();
       
   172         } catch(IOException e) {
       
   173             Main.panic("IO error: "+e.getMessage());
       
   174             return 1;
       
   175         }
       
   176 
       
   177         return 0;
       
   178     }
       
   179 
       
   180     /**
       
   181      * Generates ZoneInfoMappings in binary TLV format for each zone.
       
   182      * Regarding contents of output files, see {@link ZoneInfoFile}.
       
   183      *
       
   184      * @param Mappings
       
   185      * @return 0 if no errors, or 1 if error occurred.
       
   186      */
       
   187     int generateSrc(Mappings map) {
       
   188         try {
       
   189             int index;
       
   190             int block_size;
       
   191             int roi_size;
       
   192             long fp;
       
   193             String outputDir = Main.getOutputDir();
       
   194 
       
   195             /* If outputDir doesn't end with file-separator, adds it. */
       
   196             if (!outputDir.endsWith(File.separator)) {
       
   197                 outputDir += File.separatorChar;
       
   198             }
       
   199 
       
   200             File outD = new File(outputDir);
       
   201             outD.mkdirs();
       
   202 
       
   203             /* Open ZoneInfoMapping file to write. */
       
   204             RandomAccessFile raf =
       
   205                 new RandomAccessFile(outputDir + ZoneInfoFile.JAVAZM_FILE_NAME, "rw");
       
   206 
       
   207             /* Whether rawOffsetIndex list exists or not. */
       
   208             List<Integer> roi = map.getRawOffsetsIndex();
       
   209             if (roi == null) {
       
   210                 Main.panic("Data not exist. (rawOffsetsIndex)");
       
   211                 return 1;
       
   212             }
       
   213             roi_size = roi.size();
       
   214 
       
   215             /* Whether rawOffsetIndexTable list exists or not. */
       
   216             List<Set<String>> roit = map.getRawOffsetsIndexTable();
       
   217             if (roit == null || roit.size() != roi_size) {
       
   218                 Main.panic("Data not exist. (rawOffsetsIndexTable) Otherwise, Invalid size");
       
   219                 return 1;
       
   220             }
       
   221 
       
   222             /* Output Label */
       
   223             raf.write(ZoneInfoFile.JAVAZM_LABEL, 0,
       
   224                       ZoneInfoFile.JAVAZM_LABEL.length);
       
   225 
       
   226             /* Output Version */
       
   227             raf.writeByte(ZoneInfoFile.JAVAZM_VERSION);
       
   228 
       
   229             index = ZoneInfoFile.JAVAZM_LABEL.length + 2;
       
   230 
       
   231             /* Output Version of Olson's tzdata */
       
   232             byte[] b = Main.getVersionName().getBytes("UTF-8");
       
   233             raf.writeByte(ZoneInfoFile.TAG_TZDataVersion);
       
   234             raf.writeShort((b.length+1) & 0xFFFF);
       
   235             raf.write(b);
       
   236             raf.writeByte(0x00);
       
   237             index += b.length + 4;
       
   238 
       
   239             /* Output ID list. */
       
   240             raf.writeByte(ZoneInfoFile.TAG_ZoneIDs);
       
   241             block_size = 2;
       
   242             raf.writeShort(block_size & 0xFFFF);
       
   243             short nID = 0;
       
   244             raf.writeShort(nID & 0xFFFF);
       
   245             for (int i = 0; i < roi_size; i++) {
       
   246                 for (String key : roit.get(i)) {
       
   247                     byte size = (byte)key.getBytes("UTF-8").length;
       
   248                     raf.writeByte(size & 0xFF);
       
   249                     raf.write(key.getBytes("UTF-8"), 0, size);
       
   250                     block_size += 1 + size;
       
   251                     nID++;
       
   252                 }
       
   253             }
       
   254             fp = raf.getFilePointer();
       
   255             raf.seek(index);
       
   256             raf.writeShort((block_size) & 0xFFFF);
       
   257             raf.writeShort(nID & 0xFFFF);
       
   258             raf.seek(fp);
       
   259 
       
   260             /* Output sorted rawOffset list. */
       
   261             raf.writeByte(ZoneInfoFile.TAG_RawOffsets);
       
   262             index += 3 + block_size;
       
   263             block_size = roi_size * 4;
       
   264             raf.writeShort(block_size & 0xFFFF);
       
   265             for (int i = 0; i < roi_size; i++) {
       
   266                 raf.writeInt(Integer.parseInt(roi.get(i).toString()));
       
   267             }
       
   268 
       
   269             /* Output sorted rawOffsetIndex list. */
       
   270             raf.writeByte(ZoneInfoFile.TAG_RawOffsetIndices);
       
   271             index += 3 + block_size;
       
   272             block_size = 0;
       
   273             raf.writeShort(block_size & 0xFFFF);
       
   274             int num;
       
   275             for (int i = 0; i < roi_size; i++) {
       
   276                 num = roit.get(i).size();
       
   277                 block_size += num;
       
   278                 for (int j = 0; j < num; j++) {
       
   279                     raf.writeByte(i);
       
   280                 }
       
   281             }
       
   282             fp = raf.getFilePointer();
       
   283             raf.seek(index);
       
   284             raf.writeShort((block_size) & 0xFFFF);
       
   285             raf.seek(fp);
       
   286 
       
   287             /* Whether alias list exists or not. */
       
   288             Map<String,String> a = map.getAliases();
       
   289             if (a == null) {
       
   290                 Main.panic("Data not exist. (aliases)");
       
   291                 return 0;
       
   292             }
       
   293 
       
   294             /* Output ID list. */
       
   295             raf.writeByte(ZoneInfoFile.TAG_ZoneAliases);
       
   296             index += 3 + block_size;
       
   297             block_size = 2;
       
   298             raf.writeShort(block_size & 0xFFFF);
       
   299             raf.writeShort(a.size() & 0xFFFF);
       
   300             for (String key : a.keySet()) {
       
   301                 String alias = a.get(key);
       
   302                 byte key_size = (byte)key.length();
       
   303                 byte alias_size = (byte)alias.length();
       
   304                 raf.writeByte(key_size & 0xFF);
       
   305                 raf.write(key.getBytes("UTF-8"), 0, key_size);
       
   306                 raf.writeByte(alias_size & 0xFF);
       
   307                 raf.write(alias.getBytes("UTF-8"), 0, alias_size);
       
   308                 block_size += 2 + key_size + alias_size;
       
   309             }
       
   310             fp = raf.getFilePointer();
       
   311             raf.seek(index);
       
   312             raf.writeShort((block_size) & 0xFFFF);
       
   313             raf.seek(fp);
       
   314 
       
   315             /* Output the exclude list if it exists. */
       
   316             List<String> excludedZones = map.getExcludeList();
       
   317             if (excludedZones != null) {
       
   318                 raf.writeByte(ZoneInfoFile.TAG_ExcludedZones);
       
   319                 index += 3 + block_size;
       
   320                 block_size = 2;
       
   321                 raf.writeShort(block_size & 0xFFFF);  // place holder
       
   322                 raf.writeShort(excludedZones.size()); // the number of excluded zones
       
   323                 for (String name : excludedZones) {
       
   324                     byte size = (byte) name.length();
       
   325                     raf.writeByte(size);                 // byte length
       
   326                     raf.write(name.getBytes("UTF-8"), 0, size); // zone name
       
   327                     block_size += 1 + size;
       
   328                 }
       
   329                 fp = raf.getFilePointer();
       
   330                 raf.seek(index);
       
   331                 raf.writeShort(block_size & 0xFFFF);
       
   332                 raf.seek(fp);
       
   333             }
       
   334 
       
   335             /* Close ZoneInfoMapping file. */
       
   336             raf.close();
       
   337         } catch(IOException e) {
       
   338             Main.panic("IO error: "+e.getMessage());
       
   339             return 1;
       
   340         }
       
   341 
       
   342         return 0;
       
   343     }
       
   344 }