2 *******************************************************************************
\r
3 * Copyright (C) 1996-2010, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
7 package com.ibm.icu.impl;
\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
14 public final class ICUBinary
\r
16 // public inner interface ------------------------------------------------
\r
19 * Special interface for data authentication
\r
21 public static interface Authenticate
\r
24 * Method used in ICUBinary.readHeader() to provide data format
\r
26 * @param version version of the current data
\r
27 * @return true if dataformat is an acceptable version, false otherwise
\r
29 public boolean isDataVersionAcceptable(byte version[]);
\r
32 // public methods --------------------------------------------------------
\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
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
58 * Example of use:<br>
\r
61 * FileInputStream input = new FileInputStream(filename);
\r
62 * If (Utility.readICUDataHeader(input, dataformat, dataversion,
\r
64 * System.out.println("Verified file header, this is a ICU data file");
\r
66 * } catch (IOException e) {
\r
67 * System.out.println("This is not a ICU data file");
\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
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
81 public static final byte[] readHeader(InputStream inputStream,
\r
82 byte dataFormatIDExpected[],
\r
83 Authenticate authenticate)
\r
86 DataInputStream input = new DataInputStream(inputStream);
\r
87 char headersize = input.readChar();
\r
89 //reading the header format
\r
90 byte magic1 = input.readByte();
\r
92 byte magic2 = input.readByte();
\r
94 if (magic1 != MAGIC1 || magic2 != MAGIC2) {
\r
95 throw new IOException(MAGIC_NUMBER_AUTHENTICATION_FAILED_);
\r
98 input.readChar(); // reading size
\r
100 input.readChar(); // reading reserved word
\r
102 byte bigendian = input.readByte();
\r
104 byte charset = input.readByte();
\r
106 byte charsize = input.readByte();
\r
108 input.readByte(); // reading reserved byte
\r
111 byte dataFormatID[] = new byte[4];
\r
112 input.readFully(dataFormatID);
\r
114 byte dataVersion[] = new byte[4];
\r
115 input.readFully(dataVersion);
\r
117 byte unicodeVersion[] = new byte[4];
\r
118 input.readFully(unicodeVersion);
\r
120 if (headersize < readcount) {
\r
121 throw new IOException("Internal Error: Header size error");
\r
123 input.skipBytes(headersize - readcount);
\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
132 return unicodeVersion;
\r
135 // private variables -------------------------------------------------
\r
138 * Magic numbers to authenticate the data file
\r
140 private static final byte MAGIC1 = (byte)0xda;
\r
141 private static final byte MAGIC2 = (byte)0x27;
\r
144 * File format authentication values
\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
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