blob: 5e24ac2a899304518c483a476183c6ceb18e9027 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Portions Copyright 2003-2005 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26/*
27 *******************************************************************************
28 * (C) Copyright IBM Corp. 1996-2005 - All Rights Reserved *
29 * *
30 * The original version of this source code and documentation is copyrighted *
31 * and owned by IBM, These materials are provided under terms of a License *
32 * Agreement between IBM and Sun. This technology is protected by multiple *
33 * US and International patents. This notice and attribution to IBM may not *
34 * to removed. *
35 *******************************************************************************
36 */
37
38package sun.text.normalizer;
39
40import java.io.InputStream;
41import java.io.DataInputStream;
42import java.io.IOException;
43import java.util.Arrays;
44
45public final class ICUBinary
46{
47 // public inner interface ------------------------------------------------
48
49 /**
50 * Special interface for data authentication
51 */
52 public static interface Authenticate
53 {
54 /**
55 * Method used in ICUBinary.readHeader() to provide data format
56 * authentication.
57 * @param version version of the current data
58 * @return true if dataformat is an acceptable version, false otherwise
59 */
60 public boolean isDataVersionAcceptable(byte version[]);
61 }
62
63 // public methods --------------------------------------------------------
64
65 /**
66 * <p>ICU data header reader method.
67 * Takes a ICU generated big-endian input stream, parse the ICU standard
68 * file header and authenticates them.</p>
69 * <p>Header format:
70 * <ul>
71 * <li> Header size (char)
72 * <li> Magic number 1 (byte)
73 * <li> Magic number 2 (byte)
74 * <li> Rest of the header size (char)
75 * <li> Reserved word (char)
76 * <li> Big endian indicator (byte)
77 * <li> Character set family indicator (byte)
78 * <li> Size of a char (byte) for c++ and c use
79 * <li> Reserved byte (byte)
80 * <li> Data format identifier (4 bytes), each ICU data has its own
81 * identifier to distinguish them. [0] major [1] minor
82 * [2] milli [3] micro
83 * <li> Data version (4 bytes), the change version of the ICU data
84 * [0] major [1] minor [2] milli [3] micro
85 * <li> Unicode version (4 bytes) this ICU is based on.
86 * </ul>
87 * </p>
88 * <p>
89 * Example of use:<br>
90 * <pre>
91 * try {
92 * FileInputStream input = new FileInputStream(filename);
93 * If (Utility.readICUDataHeader(input, dataformat, dataversion,
94 * unicode) {
95 * System.out.println("Verified file header, this is a ICU data file");
96 * }
97 * } catch (IOException e) {
98 * System.out.println("This is not a ICU data file");
99 * }
100 * </pre>
101 * </p>
102 * @param inputStream input stream that contains the ICU data header
103 * @param dataFormatIDExpected Data format expected. An array of 4 bytes
104 * information about the data format.
105 * E.g. data format ID 1.2.3.4. will became an array of
106 * {1, 2, 3, 4}
107 * @param authenticate user defined extra data authentication. This value
108 * can be null, if no extra authentication is needed.
109 * @exception IOException thrown if there is a read error or
110 * when header authentication fails.
111 * @draft 2.1
112 */
113 public static final byte[] readHeader(InputStream inputStream,
114 byte dataFormatIDExpected[],
115 Authenticate authenticate)
116 throws IOException
117 {
118 DataInputStream input = new DataInputStream(inputStream);
119 char headersize = input.readChar();
120 int readcount = 2;
121 //reading the header format
122 byte magic1 = input.readByte();
123 readcount ++;
124 byte magic2 = input.readByte();
125 readcount ++;
126 if (magic1 != MAGIC1 || magic2 != MAGIC2) {
127 throw new IOException(MAGIC_NUMBER_AUTHENTICATION_FAILED_);
128 }
129
130 input.readChar(); // reading size
131 readcount += 2;
132 input.readChar(); // reading reserved word
133 readcount += 2;
134 byte bigendian = input.readByte();
135 readcount ++;
136 byte charset = input.readByte();
137 readcount ++;
138 byte charsize = input.readByte();
139 readcount ++;
140 input.readByte(); // reading reserved byte
141 readcount ++;
142
143 byte dataFormatID[] = new byte[4];
144 input.readFully(dataFormatID);
145 readcount += 4;
146 byte dataVersion[] = new byte[4];
147 input.readFully(dataVersion);
148 readcount += 4;
149 byte unicodeVersion[] = new byte[4];
150 input.readFully(unicodeVersion);
151 readcount += 4;
152 if (headersize < readcount) {
153 throw new IOException("Internal Error: Header size error");
154 }
155 input.skipBytes(headersize - readcount);
156
157 if (bigendian != BIG_ENDIAN_ || charset != CHAR_SET_
158 || charsize != CHAR_SIZE_
159 || !Arrays.equals(dataFormatIDExpected, dataFormatID)
160 || (authenticate != null
161 && !authenticate.isDataVersionAcceptable(dataVersion))) {
162 throw new IOException(HEADER_AUTHENTICATION_FAILED_);
163 }
164 return unicodeVersion;
165 }
166
167 // private variables -------------------------------------------------
168
169 /**
170 * Magic numbers to authenticate the data file
171 */
172 private static final byte MAGIC1 = (byte)0xda;
173 private static final byte MAGIC2 = (byte)0x27;
174
175 /**
176 * File format authentication values
177 */
178 private static final byte BIG_ENDIAN_ = 1;
179 private static final byte CHAR_SET_ = 0;
180 private static final byte CHAR_SIZE_ = 2;
181
182 /**
183 * Error messages
184 */
185 private static final String MAGIC_NUMBER_AUTHENTICATION_FAILED_ =
186 "ICU data file error: Not an ICU data file";
187 private static final String HEADER_AUTHENTICATION_FAILED_ =
188 "ICU data file error: Header authentication failed, please check if you have a valid ICU data file";
189}