1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.juneau.parser;
18
19 import static org.apache.juneau.commons.utils.IoUtils.*;
20 import static org.apache.juneau.commons.utils.StringUtils.*;
21 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
22 import static org.apache.juneau.commons.utils.Utils.*;
23
24 import java.io.*;
25 import java.nio.charset.*;
26
27 import org.apache.juneau.*;
28 import org.apache.juneau.commons.utils.*;
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 @SuppressWarnings("resource")
63 public class ParserPipe implements Closeable {
64
65 private final Object input;
66 final boolean debug, strict, autoCloseStreams, unbuffered;
67 private final Charset charset;
68
69 private String inputString;
70 private InputStream inputStream;
71 private Reader reader;
72 private ParserReader parserReader;
73 private boolean doClose;
74 private BinaryFormat binaryFormat;
75 private Positionable positionable;
76
77
78
79
80
81
82
83
84
85 public ParserPipe(Object input) {
86 this(input, false, false, false, false, null, null);
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 public ParserPipe(Object input, boolean debug, boolean autoCloseStreams, boolean unbuffered, BinaryFormat binaryFormat) {
106 this.input = input;
107 this.debug = debug;
108 this.strict = false;
109 this.autoCloseStreams = autoCloseStreams;
110 this.unbuffered = unbuffered;
111 this.charset = null;
112 if (input instanceof CharSequence input2)
113 this.inputString = input2.toString();
114 this.binaryFormat = binaryFormat;
115 }
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140 public ParserPipe(Object input, boolean debug, boolean strict, boolean autoCloseStreams, boolean unbuffered, Charset streamCharset, Charset fileCharset) {
141 boolean isFile = input instanceof File;
142 this.input = input;
143 this.debug = debug;
144 this.strict = strict;
145 this.autoCloseStreams = autoCloseStreams;
146 this.unbuffered = unbuffered;
147 Charset cs = isFile ? fileCharset : streamCharset;
148 if (cs == null)
149 cs = (isFile ? Charset.defaultCharset() : UTF8);
150 this.charset = cs;
151 if (input instanceof CharSequence cs2)
152 this.inputString = cs2.toString();
153 this.binaryFormat = null;
154 }
155
156
157
158
159
160
161
162 public String asString() throws IOException {
163 if (inputString == null)
164 inputString = read(getReader());
165 return inputString;
166 }
167
168 @Override
169 public void close() {
170 try {
171 if (doClose)
172 IoUtils.close(reader, inputStream);
173 } catch (IOException e) {
174 throw bex(e);
175 }
176 }
177
178
179
180
181
182
183
184
185
186
187 public Reader getBufferedReader() throws IOException { return toBufferedReader(getReader()); }
188
189
190
191
192
193
194
195
196
197 public String getInputAsString() { return inputString; }
198
199
200
201
202
203
204
205
206
207
208 public InputStream getInputStream() throws IOException {
209 if (input == null)
210 return null;
211
212 if (input instanceof InputStream input2) {
213 if (debug) {
214 var b = readBytes(input2);
215 inputString = toHex(b);
216 inputStream = new ByteArrayInputStream(b);
217 } else {
218 inputStream = input2;
219 doClose = autoCloseStreams;
220 }
221 } else if (input instanceof byte[]) {
222 if (debug)
223 inputString = toHex((byte[])input);
224 inputStream = new ByteArrayInputStream((byte[])input);
225 doClose = false;
226 } else if (input instanceof String input2) {
227 inputString = input2;
228 inputStream = new ByteArrayInputStream(convertFromString(input2));
229 doClose = false;
230 } else if (input instanceof File input2) {
231 if (debug) {
232 var b = readBytes(input2);
233 inputString = toHex(b);
234 inputStream = new ByteArrayInputStream(b);
235 } else {
236 inputStream = new FileInputStream(input2);
237 doClose = true;
238 }
239 } else {
240 throw ioex("Cannot convert object of type {0} to an InputStream.", cn(input));
241 }
242
243 return inputStream;
244 }
245
246
247
248
249
250
251
252 public ParserReader getParserReader() throws IOException {
253 if (input == null)
254 return null;
255 if (input instanceof ParserReader input2)
256 parserReader = input2;
257 else
258 parserReader = new ParserReader(this);
259 return parserReader;
260 }
261
262
263
264
265
266
267
268
269
270
271 public Reader getReader() throws IOException {
272 if (input == null)
273 return null;
274
275 if (input instanceof Reader input2) {
276 if (debug) {
277 inputString = read(input2);
278 reader = new StringReader(inputString);
279 } else {
280 reader = input2;
281 doClose = autoCloseStreams;
282 }
283 } else if (input instanceof CharSequence input2) {
284 inputString = input2.toString();
285 reader = new ParserReader(this);
286 doClose = false;
287 } else if (input instanceof InputStream || input instanceof byte[]) {
288 doClose = input instanceof InputStream && autoCloseStreams;
289 InputStream is = (input instanceof InputStream input2 ? input2 : new ByteArrayInputStream((byte[])input));
290 CharsetDecoder cd = charset.newDecoder();
291 if (strict) {
292 cd.onMalformedInput(CodingErrorAction.REPORT);
293 cd.onUnmappableCharacter(CodingErrorAction.REPORT);
294 } else {
295 cd.onMalformedInput(CodingErrorAction.REPLACE);
296 cd.onUnmappableCharacter(CodingErrorAction.REPLACE);
297 }
298 reader = new InputStreamReader(is, cd);
299 if (debug) {
300 inputString = read(reader);
301 reader = new StringReader(inputString);
302 }
303 } else if (input instanceof File input2) {
304 CharsetDecoder cd = charset.newDecoder();
305 if (strict) {
306 cd.onMalformedInput(CodingErrorAction.REPORT);
307 cd.onUnmappableCharacter(CodingErrorAction.REPORT);
308 } else {
309 cd.onMalformedInput(CodingErrorAction.REPLACE);
310 cd.onUnmappableCharacter(CodingErrorAction.REPLACE);
311 }
312 reader = new InputStreamReader(new FileInputStream(input2), cd);
313 if (debug) {
314 inputString = read(reader);
315 reader = new StringReader(inputString);
316 }
317 doClose = true;
318 } else {
319 throw ioex("Cannot convert object of type {0} to an InputStream.", cn(input));
320 }
321
322 return reader;
323 }
324
325
326
327
328
329
330 public boolean isString() { return nn(inputString); }
331
332
333
334
335
336
337
338
339
340 public void setPositionable(Positionable positionable) { this.positionable = positionable; }
341
342 private byte[] convertFromString(String in) {
343 return switch (binaryFormat) {
344 case BASE64 -> base64Decode(in);
345 case HEX -> fromHex(in);
346 case SPACED_HEX -> fromSpacedHex(in);
347 default -> new byte[0];
348 };
349 }
350
351 Position getPosition() {
352 if (positionable == null)
353 return Position.UNKNOWN;
354 Position p = positionable.getPosition();
355 if (p == null)
356 return Position.UNKNOWN;
357 return p;
358 }
359 }