]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/classes/core/src/com/ibm/icu/impl/ICUBinary.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / classes / core / src / com / ibm / icu / impl / ICUBinary.java
1 /*
2  *******************************************************************************
3  * Copyright (C) 1996-2010, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.impl;
8
9 import java.io.DataInputStream;
10 import java.io.IOException;
11 import java.io.InputStream;
12 import java.util.Arrays;
13
14 import com.ibm.icu.util.VersionInfo;
15
16 public final class ICUBinary 
17 {    
18     // public inner interface ------------------------------------------------
19     
20     /**
21      * Special interface for data authentication
22      */
23     public static interface Authenticate
24     {
25         /**
26          * Method used in ICUBinary.readHeader() to provide data format
27          * authentication. 
28          * @param version version of the current data
29          * @return true if dataformat is an acceptable version, false otherwise
30          */
31         public boolean isDataVersionAcceptable(byte version[]);
32     }
33     
34     // public methods --------------------------------------------------------
35     
36     /**
37     * <p>ICU data header reader method. 
38     * Takes a ICU generated big-endian input stream, parse the ICU standard 
39     * file header and authenticates them.</p>
40     * <p>Header format: 
41     * <ul>
42     *     <li> Header size (char)
43     *     <li> Magic number 1 (byte)
44     *     <li> Magic number 2 (byte)
45     *     <li> Rest of the header size (char)
46     *     <li> Reserved word (char)
47     *     <li> Big endian indicator (byte)
48     *     <li> Character set family indicator (byte)
49     *     <li> Size of a char (byte) for c++ and c use
50     *     <li> Reserved byte (byte)
51     *     <li> Data format identifier (4 bytes), each ICU data has its own
52     *          identifier to distinguish them. [0] major [1] minor 
53     *                                          [2] milli [3] micro 
54     *     <li> Data version (4 bytes), the change version of the ICU data
55     *                             [0] major [1] minor [2] milli [3] micro 
56     *     <li> Unicode version (4 bytes) this ICU is based on.
57     * </ul>
58     * </p>
59     * <p>
60     * Example of use:<br>
61     * <pre>
62     * try {
63     *    FileInputStream input = new FileInputStream(filename);
64     *    If (Utility.readICUDataHeader(input, dataformat, dataversion, 
65     *                                  unicode) {
66     *        System.out.println("Verified file header, this is a ICU data file");
67     *    }
68     * } catch (IOException e) {
69     *    System.out.println("This is not a ICU data file");
70     * }
71     * </pre>
72     * </p>
73     * @param inputStream input stream that contains the ICU data header
74     * @param dataFormatIDExpected Data format expected. An array of 4 bytes 
75     *                     information about the data format.
76     *                     E.g. data format ID 1.2.3.4. will became an array of 
77     *                     {1, 2, 3, 4}
78     * @param authenticate user defined extra data authentication. This value
79     *                     can be null, if no extra authentication is needed.
80     * @exception IOException thrown if there is a read error or 
81     *            when header authentication fails.
82     */
83     public static final byte[] readHeader(InputStream inputStream,
84                                         byte dataFormatIDExpected[],
85                                         Authenticate authenticate) 
86                                                           throws IOException
87     {
88         DataInputStream input = new DataInputStream(inputStream);
89         char headersize = input.readChar();
90         int readcount = 2;
91         //reading the header format
92         byte magic1 = input.readByte();
93         readcount ++;
94         byte magic2 = input.readByte();
95         readcount ++;
96         if (magic1 != MAGIC1 || magic2 != MAGIC2) {
97             throw new IOException(MAGIC_NUMBER_AUTHENTICATION_FAILED_);
98         }
99         
100         input.readChar(); // reading size
101         readcount += 2;
102         input.readChar(); // reading reserved word
103         readcount += 2;
104         byte bigendian    = input.readByte();
105         readcount ++;
106         byte charset      = input.readByte();
107         readcount ++;
108         byte charsize     = input.readByte();
109         readcount ++;
110         input.readByte(); // reading reserved byte
111         readcount ++;
112                 
113         byte dataFormatID[] = new byte[4];
114         input.readFully(dataFormatID);
115         readcount += 4;
116         byte dataVersion[] = new byte[4];
117         input.readFully(dataVersion);
118         readcount += 4;
119         byte unicodeVersion[] = new byte[4];
120         input.readFully(unicodeVersion);
121         readcount += 4;
122         if (headersize < readcount) {
123             throw new IOException("Internal Error: Header size error");
124         }
125         input.skipBytes(headersize - readcount);
126
127         if (bigendian != BIG_ENDIAN_ || charset != CHAR_SET_
128             || charsize != CHAR_SIZE_
129             || !Arrays.equals(dataFormatIDExpected, dataFormatID)
130             || (authenticate != null 
131                 && !authenticate.isDataVersionAcceptable(dataVersion))) {
132             throw new IOException(HEADER_AUTHENTICATION_FAILED_);
133         }
134         return unicodeVersion;
135     }
136
137     /**
138      * Same as readHeader(), but returns a VersionInfo rather than a byte[].
139      */
140     public static final VersionInfo readHeaderAndDataVersion(InputStream inputStream,
141                                                              byte dataFormatIDExpected[],
142                                                              Authenticate authenticate)
143                                                                 throws IOException {
144         byte[] dataVersion = readHeader(inputStream, dataFormatIDExpected, authenticate);
145         return VersionInfo.getInstance(dataVersion[0], dataVersion[1],
146                                        dataVersion[2], dataVersion[3]);
147     }
148
149     // private variables -------------------------------------------------
150   
151     /**
152     * Magic numbers to authenticate the data file
153     */
154     private static final byte MAGIC1 = (byte)0xda;
155     private static final byte MAGIC2 = (byte)0x27;
156       
157     /**
158     * File format authentication values
159     */
160     private static final byte BIG_ENDIAN_ = 1;
161     private static final byte CHAR_SET_ = 0;
162     private static final byte CHAR_SIZE_ = 2;
163                                                     
164     /**
165     * Error messages
166     */
167     private static final String MAGIC_NUMBER_AUTHENTICATION_FAILED_ = 
168                        "ICU data file error: Not an ICU data file";
169     private static final String HEADER_AUTHENTICATION_FAILED_ =
170         "ICU data file error: Header authentication failed, please check if you have a valid ICU data file";
171 }