1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ccsds.utils.lexical;
18
19 import java.io.BufferedInputStream;
20 import java.io.BufferedReader;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.Reader;
24
25 import org.orekit.data.DataSource;
26 import org.orekit.errors.OrekitException;
27 import org.orekit.errors.OrekitMessages;
28
29
30
31
32
33
34 public class LexicalAnalyzerSelector {
35
36
37 private static final int BUFFER = 4096;
38
39
40 private static final byte[] UCS_4_BE_BOM = {
41 0x00, 0x00, -0x02, -0X01, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6c
42 };
43
44
45 private static final byte[] UCS_4_LE_BOM = {
46 -0x01, -0X02, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00
47 };
48
49
50 private static final byte[] UTF_16_BE_BOM = {
51 -0x02, -0X01, 0x00, 0x3c, 0x00, 0x3f, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c
52 };
53
54
55 private static final byte[] UTF_16_LE_BOM = {
56 -0x01, -0X02, 0x3c, 0x00, 0x3f, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00
57 };
58
59
60 private static final byte[] UTF_8_BOM = {
61 -0x11, -0x45, -0x41, 0x3c, 0x3f, 0x78, 0x6d, 0x6c
62 };
63
64
65 private static final byte[] UCS_4_BE = {
66 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6c
67 };
68
69
70 private static final byte[] UCS_4_LE = {
71 0x3c, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x6c, 0x00, 0x00, 0x00
72 };
73
74
75 private static final byte[] UTF_16_BE = {
76 0x00, 0x3c, 0x00, 0x3f, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c
77 };
78
79
80 private static final byte[] UTF_16_LE = {
81 0x3c, 0x00, 0x3f, 0x00, 0x78, 0x00, 0x6d, 0x00, 0x6c, 0x00
82 };
83
84
85 private static final byte[] UTF_8 = {
86 0x3c, 0x3f, 0x78, 0x6d, 0x6c
87 };
88
89
90 private static final String CHARS_BOM = "\ufeff<?xml";
91
92
93 private static final String CHARS = "<?xml";
94
95
96
97 private LexicalAnalyzerSelector() {
98
99 }
100
101
102
103
104
105
106 public static LexicalAnalyzer select(final DataSource source) throws IOException {
107 final DataSource.Opener opener = source.getOpener();
108 if (opener.rawDataIsBinary()) {
109 return select(source.getName(), opener.openStreamOnce());
110 } else {
111 return select(source.getName(), opener.openReaderOnce());
112 }
113 }
114
115
116
117
118
119
120
121 private static LexicalAnalyzer select(final String name, final InputStream stream) throws IOException {
122
123 if (stream == null) {
124 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, name);
125 }
126 final BufferedInputStream bis = new BufferedInputStream(stream, BUFFER);
127
128
129 final int size = UCS_4_BE_BOM.length;
130 bis.mark(size);
131 final byte[] first = new byte[size];
132 int read = 0;
133 while (read < first.length) {
134 final int n = bis.read(first, read, size - read);
135 if (n < 0) {
136
137
138
139 bis.reset();
140 return new KvnLexicalAnalyzer(new DataSource(name, () -> bis));
141 }
142 read += n;
143 }
144
145
146
147
148
149 if (checkSequence(first, UTF_8) || checkSequence(first, UTF_8_BOM) ||
150 checkSequence(first, UTF_16_LE) || checkSequence(first, UTF_16_LE_BOM) ||
151 checkSequence(first, UTF_16_BE) || checkSequence(first, UTF_16_BE_BOM) ||
152 checkSequence(first, UCS_4_LE) || checkSequence(first, UCS_4_LE_BOM) ||
153 checkSequence(first, UCS_4_BE) || checkSequence(first, UCS_4_BE_BOM)) {
154
155 bis.reset();
156 return new XmlLexicalAnalyzer(new DataSource(name, () -> bis));
157 } else {
158
159 bis.reset();
160 return new KvnLexicalAnalyzer(new DataSource(name, () -> bis));
161 }
162
163 }
164
165
166
167
168
169
170
171 private static LexicalAnalyzer select(final String name, final Reader reader) throws IOException {
172
173 if (reader == null) {
174 throw new OrekitException(OrekitMessages.UNABLE_TO_FIND_FILE, name);
175 }
176 final BufferedReader br = new BufferedReader(reader, BUFFER);
177
178
179 final int size = CHARS_BOM.length();
180 br.mark(size);
181 final char[] first = new char[size];
182 int read = 0;
183 while (read < first.length) {
184 final int n = br.read(first, read, size - read);
185 if (n < 0) {
186
187
188
189 br.reset();
190 return new KvnLexicalAnalyzer(new DataSource(name, () -> br));
191 }
192 read += n;
193 }
194 final String firstString = new String(first);
195
196
197 if (firstString.startsWith(CHARS) || CHARS_BOM.equals(firstString)) {
198
199 br.reset();
200 return new XmlLexicalAnalyzer(new DataSource(name, () -> br));
201 } else {
202
203 br.reset();
204 return new KvnLexicalAnalyzer(new DataSource(name, () -> br));
205 }
206
207 }
208
209
210
211
212
213
214 private static boolean checkSequence(final byte[] first, final byte[] reference) {
215 for (int i = 0; i < reference.length; ++i) {
216 if (first[i] != reference[i]) {
217 return false;
218 }
219 }
220 return true;
221 }
222
223 }