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