1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.io.build;
19
20 import java.io.ByteArrayInputStream;
21 import java.io.File;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.InputStreamReader;
26 import java.io.OutputStream;
27 import java.io.OutputStreamWriter;
28 import java.io.RandomAccessFile;
29 import java.io.Reader;
30 import java.io.Writer;
31 import java.net.URI;
32 import java.nio.charset.Charset;
33 import java.nio.file.Files;
34 import java.nio.file.OpenOption;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.nio.file.StandardOpenOption;
38 import java.nio.file.spi.FileSystemProvider;
39 import java.util.Arrays;
40 import java.util.Objects;
41
42 import org.apache.commons.io.IORandomAccessFile;
43 import org.apache.commons.io.IOUtils;
44 import org.apache.commons.io.RandomAccessFileMode;
45 import org.apache.commons.io.RandomAccessFiles;
46 import org.apache.commons.io.file.spi.FileSystemProviders;
47 import org.apache.commons.io.input.BufferedFileChannelInputStream;
48 import org.apache.commons.io.input.CharSequenceInputStream;
49 import org.apache.commons.io.input.CharSequenceReader;
50 import org.apache.commons.io.input.ReaderInputStream;
51 import org.apache.commons.io.output.RandomAccessFileOutputStream;
52 import org.apache.commons.io.output.WriterOutputStream;
53
54
55
56
57
58
59
60
61
62
63
64
65
66 public abstract class AbstractOrigin<T, B extends AbstractOrigin<T, B>> extends AbstractSupplier<T, B> {
67
68
69
70
71
72
73
74
75
76
77
78 public abstract static class AbstractRandomAccessFileOrigin<T extends RandomAccessFile, B extends AbstractRandomAccessFileOrigin<T, B>>
79 extends AbstractOrigin<T, B> {
80
81
82
83
84
85
86
87
88
89 public AbstractRandomAccessFileOrigin(final T origin) {
90 super(origin);
91 }
92
93 @Override
94 public byte[] getByteArray() throws IOException {
95 final long longLen = origin.length();
96 if (longLen > Integer.MAX_VALUE) {
97 throw new IllegalStateException("Origin too large.");
98 }
99 return RandomAccessFiles.read(origin, 0, (int) longLen);
100 }
101
102 @Override
103 public byte[] getByteArray(final long position, final int length) throws IOException {
104 return RandomAccessFiles.read(origin, position, length);
105 }
106
107 @Override
108 public CharSequence getCharSequence(final Charset charset) throws IOException {
109 return new String(getByteArray(), charset);
110 }
111
112 @SuppressWarnings("resource")
113 @Override
114 public InputStream getInputStream(final OpenOption... options) throws IOException {
115 return BufferedFileChannelInputStream.builder().setFileChannel(origin.getChannel()).get();
116 }
117
118 @Override
119 public OutputStream getOutputStream(final OpenOption... options) throws IOException {
120 return RandomAccessFileOutputStream.builder().setRandomAccessFile(origin).get();
121 }
122
123 @Override
124 public T getRandomAccessFile(final OpenOption... openOption) {
125
126 return get();
127 }
128
129 @Override
130 public Reader getReader(final Charset charset) throws IOException {
131 return new InputStreamReader(getInputStream(), charset);
132 }
133
134 @Override
135 public Writer getWriter(final Charset charset, final OpenOption... options) throws IOException {
136 return new OutputStreamWriter(getOutputStream(options), charset);
137 }
138
139 @Override
140 public long size() throws IOException {
141 return origin.length();
142 }
143 }
144
145
146
147
148 public static class ByteArrayOrigin extends AbstractOrigin<byte[], ByteArrayOrigin> {
149
150
151
152
153
154
155 public ByteArrayOrigin(final byte[] origin) {
156 super(origin);
157 }
158
159 @Override
160 public byte[] getByteArray() {
161
162 return get();
163 }
164
165
166
167
168
169
170
171 @Override
172 public InputStream getInputStream(final OpenOption... options) throws IOException {
173 return new ByteArrayInputStream(origin);
174 }
175
176 @Override
177 public Reader getReader(final Charset charset) throws IOException {
178 return new InputStreamReader(getInputStream(), charset);
179 }
180
181 @Override
182 public long size() throws IOException {
183 return origin.length;
184 }
185
186 }
187
188
189
190
191 public static class CharSequenceOrigin extends AbstractOrigin<CharSequence, CharSequenceOrigin> {
192
193
194
195
196
197
198 public CharSequenceOrigin(final CharSequence origin) {
199 super(origin);
200 }
201
202 @Override
203 public byte[] getByteArray() {
204
205 return origin.toString().getBytes(Charset.defaultCharset());
206 }
207
208
209
210
211
212
213
214 @Override
215 public CharSequence getCharSequence(final Charset charset) {
216
217 return get();
218 }
219
220
221
222
223
224
225
226 @Override
227 public InputStream getInputStream(final OpenOption... options) throws IOException {
228
229 return CharSequenceInputStream.builder().setCharSequence(getCharSequence(Charset.defaultCharset())).get();
230 }
231
232
233
234
235
236
237
238 @Override
239 public Reader getReader(final Charset charset) throws IOException {
240 return new CharSequenceReader(get());
241 }
242
243 @Override
244 public long size() throws IOException {
245 return origin.length();
246 }
247
248 }
249
250
251
252
253
254
255
256 public static class FileOrigin extends AbstractOrigin<File, FileOrigin> {
257
258
259
260
261
262
263 public FileOrigin(final File origin) {
264 super(origin);
265 }
266
267 @Override
268 public byte[] getByteArray(final long position, final int length) throws IOException {
269 try (RandomAccessFile raf = RandomAccessFileMode.READ_ONLY.create(origin)) {
270 return RandomAccessFiles.read(raf, position, length);
271 }
272 }
273
274 @Override
275 public File getFile() {
276
277 return get();
278 }
279
280 @Override
281 public Path getPath() {
282 return get().toPath();
283 }
284
285 }
286
287
288
289
290
291
292
293 public static class InputStreamOrigin extends AbstractOrigin<InputStream, InputStreamOrigin> {
294
295
296
297
298
299
300 public InputStreamOrigin(final InputStream origin) {
301 super(origin);
302 }
303
304 @Override
305 public byte[] getByteArray() throws IOException {
306 return IOUtils.toByteArray(origin);
307 }
308
309
310
311
312
313
314
315 @Override
316 public InputStream getInputStream(final OpenOption... options) {
317
318 return get();
319 }
320
321 @Override
322 public Reader getReader(final Charset charset) throws IOException {
323 return new InputStreamReader(getInputStream(), charset);
324 }
325
326 }
327
328
329
330
331
332
333 public static class IORandomAccessFileOrigin extends AbstractRandomAccessFileOrigin<IORandomAccessFile, IORandomAccessFileOrigin> {
334
335
336
337
338
339
340 public IORandomAccessFileOrigin(final IORandomAccessFile origin) {
341 super(origin);
342 }
343
344 @SuppressWarnings("resource")
345 @Override
346 public File getFile() {
347 return get().getFile();
348 }
349
350 @Override
351 public Path getPath() {
352 return getFile().toPath();
353 }
354
355 }
356
357
358
359
360
361
362
363 public static class OutputStreamOrigin extends AbstractOrigin<OutputStream, OutputStreamOrigin> {
364
365
366
367
368
369
370 public OutputStreamOrigin(final OutputStream origin) {
371 super(origin);
372 }
373
374
375
376
377
378
379
380 @Override
381 public OutputStream getOutputStream(final OpenOption... options) {
382
383 return get();
384 }
385
386
387
388
389
390
391
392 @Override
393 public Writer getWriter(final Charset charset, final OpenOption... options) throws IOException {
394 return new OutputStreamWriter(origin, charset);
395 }
396 }
397
398
399
400
401
402
403
404 public static class PathOrigin extends AbstractOrigin<Path, PathOrigin> {
405
406
407
408
409
410
411 public PathOrigin(final Path origin) {
412 super(origin);
413 }
414
415 @Override
416 public byte[] getByteArray(final long position, final int length) throws IOException {
417 return RandomAccessFileMode.READ_ONLY.apply(origin, raf -> RandomAccessFiles.read(raf, position, length));
418 }
419
420 @Override
421 public File getFile() {
422 return get().toFile();
423 }
424
425 @Override
426 public Path getPath() {
427
428 return get();
429 }
430
431 }
432
433
434
435
436
437
438
439
440 public static class RandomAccessFileOrigin extends AbstractRandomAccessFileOrigin<RandomAccessFile, RandomAccessFileOrigin> {
441
442
443
444
445
446
447
448
449
450 public RandomAccessFileOrigin(final RandomAccessFile origin) {
451 super(origin);
452 }
453
454 }
455
456
457
458
459
460
461
462 public static class ReaderOrigin extends AbstractOrigin<Reader, ReaderOrigin> {
463
464
465
466
467
468
469 public ReaderOrigin(final Reader origin) {
470 super(origin);
471 }
472
473 @Override
474 public byte[] getByteArray() throws IOException {
475
476 return IOUtils.toByteArray(origin, Charset.defaultCharset());
477 }
478
479
480
481
482
483
484
485 @Override
486 public CharSequence getCharSequence(final Charset charset) throws IOException {
487 return IOUtils.toString(origin);
488 }
489
490
491
492
493
494
495
496 @Override
497 public InputStream getInputStream(final OpenOption... options) throws IOException {
498
499 return ReaderInputStream.builder().setReader(origin).setCharset(Charset.defaultCharset()).get();
500 }
501
502
503
504
505
506
507
508 @Override
509 public Reader getReader(final Charset charset) throws IOException {
510
511 return get();
512 }
513 }
514
515
516
517
518 public static class URIOrigin extends AbstractOrigin<URI, URIOrigin> {
519
520 private static final String SCHEME_HTTPS = "https";
521 private static final String SCHEME_HTTP = "http";
522
523
524
525
526
527
528 public URIOrigin(final URI origin) {
529 super(origin);
530 }
531
532 @Override
533 public File getFile() {
534 return getPath().toFile();
535 }
536
537 @Override
538 public InputStream getInputStream(final OpenOption... options) throws IOException {
539 final URI uri = get();
540 final String scheme = uri.getScheme();
541 final FileSystemProvider fileSystemProvider = FileSystemProviders.installed().getFileSystemProvider(scheme);
542 if (fileSystemProvider != null) {
543 return Files.newInputStream(fileSystemProvider.getPath(uri), options);
544 }
545 if (SCHEME_HTTP.equalsIgnoreCase(scheme) || SCHEME_HTTPS.equalsIgnoreCase(scheme)) {
546 return uri.toURL().openStream();
547 }
548 return Files.newInputStream(getPath(), options);
549 }
550
551 @Override
552 public Path getPath() {
553 return Paths.get(get());
554 }
555 }
556
557
558
559
560
561
562
563 public static class WriterOrigin extends AbstractOrigin<Writer, WriterOrigin> {
564
565
566
567
568
569
570 public WriterOrigin(final Writer origin) {
571 super(origin);
572 }
573
574
575
576
577
578
579
580 @Override
581 public OutputStream getOutputStream(final OpenOption... options) throws IOException {
582
583 return WriterOutputStream.builder().setWriter(origin).setCharset(Charset.defaultCharset()).get();
584 }
585
586
587
588
589
590
591
592
593
594
595 @Override
596 public Writer getWriter(final Charset charset, final OpenOption... options) throws IOException {
597
598 return get();
599 }
600 }
601
602
603
604
605 final T origin;
606
607
608
609
610
611
612 protected AbstractOrigin(final T origin) {
613 this.origin = Objects.requireNonNull(origin, "origin");
614 }
615
616
617
618
619
620
621 @Override
622 public T get() {
623 return origin;
624 }
625
626
627
628
629
630
631
632
633 public byte[] getByteArray() throws IOException {
634 return Files.readAllBytes(getPath());
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648 public byte[] getByteArray(final long position, final int length) throws IOException {
649 final byte[] bytes = getByteArray();
650
651 final int start = Math.toIntExact(position);
652 if (start < 0 || length < 0 || start + length < 0 || start + length > bytes.length) {
653 throw new IllegalArgumentException("Couldn't read array (start: " + start + ", length: " + length + ", data length: " + bytes.length + ").");
654 }
655 return Arrays.copyOfRange(bytes, start, start + length);
656 }
657
658
659
660
661
662
663
664
665
666 public CharSequence getCharSequence(final Charset charset) throws IOException {
667 return new String(getByteArray(), charset);
668 }
669
670
671
672
673
674
675
676 public File getFile() {
677 throw new UnsupportedOperationException(
678 String.format("%s#getFile() for %s origin %s", getSimpleClassName(), origin.getClass().getSimpleName(), origin));
679 }
680
681
682
683
684
685
686
687
688
689 public InputStream getInputStream(final OpenOption... options) throws IOException {
690 return Files.newInputStream(getPath(), options);
691 }
692
693
694
695
696
697
698
699
700
701 public OutputStream getOutputStream(final OpenOption... options) throws IOException {
702 return Files.newOutputStream(getPath(), options);
703 }
704
705
706
707
708
709
710
711 public Path getPath() {
712 throw new UnsupportedOperationException(
713 String.format("%s#getPath() for %s origin %s", getSimpleClassName(), origin.getClass().getSimpleName(), origin));
714 }
715
716
717
718
719
720
721
722
723
724
725 public RandomAccessFile getRandomAccessFile(final OpenOption... openOption) throws FileNotFoundException {
726 return RandomAccessFileMode.valueOf(openOption).create(getFile());
727 }
728
729
730
731
732
733
734
735
736 public Reader getReader(final Charset charset) throws IOException {
737 return Files.newBufferedReader(getPath(), charset);
738 }
739
740 private String getSimpleClassName() {
741 return getClass().getSimpleName();
742 }
743
744
745
746
747
748
749
750
751
752
753 public Writer getWriter(final Charset charset, final OpenOption... options) throws IOException {
754 return Files.newBufferedWriter(getPath(), charset, options);
755 }
756
757
758
759
760
761
762
763
764 public long size() throws IOException {
765 return Files.size(getPath());
766 }
767
768 @Override
769 public String toString() {
770 return getSimpleClassName() + "[" + origin.toString() + "]";
771 }
772 }