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