1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs2.provider;
18
19 import java.io.BufferedInputStream;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.io.OutputStream;
24 import java.net.URL;
25 import java.security.AccessController;
26 import java.security.PrivilegedActionException;
27 import java.security.PrivilegedExceptionAction;
28 import java.security.cert.Certificate;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collections;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.concurrent.atomic.AtomicReference;
37 import java.util.stream.Stream;
38
39 import org.apache.commons.io.IOUtils;
40 import org.apache.commons.io.function.Uncheck;
41 import org.apache.commons.vfs2.Capability;
42 import org.apache.commons.vfs2.FileContent;
43 import org.apache.commons.vfs2.FileContentInfoFactory;
44 import org.apache.commons.vfs2.FileName;
45 import org.apache.commons.vfs2.FileNotFolderException;
46 import org.apache.commons.vfs2.FileObject;
47 import org.apache.commons.vfs2.FileSelector;
48 import org.apache.commons.vfs2.FileSystem;
49 import org.apache.commons.vfs2.FileSystemException;
50 import org.apache.commons.vfs2.FileType;
51 import org.apache.commons.vfs2.NameScope;
52 import org.apache.commons.vfs2.RandomAccessContent;
53 import org.apache.commons.vfs2.Selectors;
54 import org.apache.commons.vfs2.operations.DefaultFileOperations;
55 import org.apache.commons.vfs2.operations.FileOperations;
56 import org.apache.commons.vfs2.util.FileObjectUtils;
57 import org.apache.commons.vfs2.util.RandomAccessMode;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72 public abstract class AbstractFileObject<AFS extends AbstractFileSystem> implements FileObject {
73
74
75
76
77 public static final int DEFAULT_BUFFER_SIZE = 8192;
78
79 private static final int INITIAL_LIST_SIZE = 5;
80
81 private static final String DO_GET_INPUT_STREAM_INT = "doGetInputStream(int)";
82
83
84
85
86 private static void traverse(final DefaultFileSelectorInfo fileInfo, final FileSelector selector,
87 final boolean depthwise, final List<FileObject> selected) throws Exception {
88
89 final FileObject file = fileInfo.getFile();
90 final int index = selected.size();
91
92
93 if (file.getType().hasChildren() && selector.traverseDescendants(fileInfo)) {
94 final int curDepth = fileInfo.getDepth();
95 fileInfo.setDepth(curDepth + 1);
96
97
98 final FileObject[] children = file.getChildren();
99 for (final FileObject child : children) {
100 fileInfo.setFile(child);
101 traverse(fileInfo, selector, depthwise, selected);
102 }
103
104 fileInfo.setFile(file);
105 fileInfo.setDepth(curDepth);
106 }
107
108
109 if (selector.includeFile(fileInfo)) {
110 if (depthwise) {
111
112 selected.add(file);
113 } else {
114
115 selected.add(index, file);
116 }
117 }
118 }
119 private final AbstractFileName fileName;
120
121 private final AFS fileSystem;
122 private FileContent content;
123
124 private boolean attached;
125
126 private FileType type;
127 private FileObject parent;
128
129
130
131
132 private FileName[] children;
133
134 private List<Object> objects;
135
136
137
138
139 private FileOperations operations;
140
141
142
143
144
145
146
147 protected AbstractFileObject(final AbstractFileName fileName, final AFS fileSystem) {
148 this.fileName = fileName;
149 this.fileSystem = fileSystem;
150 fileSystem.fileObjectHanded(this);
151 }
152
153
154
155
156
157
158 private void attach() throws FileSystemException {
159 synchronized (fileSystem) {
160 if (attached) {
161 return;
162 }
163
164 try {
165
166 doAttach();
167 attached = true;
168
169
170
171
172
173
174 } catch (final Exception exc) {
175 throw new FileSystemException("vfs.provider/get-type.error", exc, fileName);
176 }
177
178
179 }
180 }
181
182
183
184
185
186
187
188 @Override
189 public boolean canRenameTo(final FileObject newfile) {
190 return fileSystem == newfile.getFileSystem();
191 }
192
193
194
195
196
197
198
199
200 protected void childrenChanged(final FileName childName, final FileType newType) throws Exception {
201
202
203 if (children != null && childName != null && newType != null) {
204
205 final ArrayList<FileName> list = new ArrayList<>(Arrays.asList(children));
206 if (newType.equals(FileType.IMAGINARY)) {
207 list.remove(childName);
208 } else {
209 list.add(childName);
210 }
211 children = list.toArray(FileName.EMPTY_ARRAY);
212 }
213
214
215 onChildrenChanged(childName, newType);
216 }
217
218
219
220
221
222
223 @Override
224 public void close() throws FileSystemException {
225 AtomicReference<Exception> ref = new AtomicReference<>();
226 synchronized (fileSystem) {
227
228 IOUtils.closeQuietly(content, ref::set);
229 if (ref.get() != null) {
230 content = null;
231 }
232
233 try {
234 detach();
235 } catch (final Exception e) {
236 ref.set(e);
237 }
238 if (ref.get() != null) {
239 throw new FileSystemException("vfs.provider/close.error", fileName, ref.get());
240 }
241 }
242 }
243
244
245
246
247
248
249
250
251 @Override
252 public int compareTo(final FileObject file) {
253 if (file == null) {
254 return 1;
255 }
256 return this.toString().compareToIgnoreCase(file.toString());
257 }
258
259
260
261
262
263
264
265
266 @Override
267 public void copyFrom(final FileObject file, final FileSelector selector) throws FileSystemException {
268 if (!FileObjectUtils.exists(file)) {
269 throw new FileSystemException("vfs.provider/copy-missing-file.error", file);
270 }
271
272
273 final ArrayList<FileObject> files = new ArrayList<>();
274 file.findFiles(selector, false, files);
275
276
277 for (final FileObject srcFile : files) {
278
279 final String relPath = file.getName().getRelativeName(srcFile.getName());
280 final FileObject destFile = resolveFile(relPath, NameScope.DESCENDENT_OR_SELF);
281
282
283 if (FileObjectUtils.exists(destFile) && destFile.getType() != srcFile.getType()) {
284
285
286
287 destFile.deleteAll();
288 }
289
290
291 try {
292 if (srcFile.getType().hasContent()) {
293 FileObjectUtils.writeContent(srcFile, destFile);
294 } else if (srcFile.getType().hasChildren()) {
295 destFile.createFolder();
296 }
297 } catch (final IOException e) {
298 throw new FileSystemException("vfs.provider/copy-file.error", e, srcFile, destFile);
299 }
300 }
301 }
302
303
304
305
306
307
308 @Override
309 public void createFile() throws FileSystemException {
310 synchronized (fileSystem) {
311 try {
312
313
314 if (exists() && !isFile()) {
315 throw new FileSystemException("vfs.provider/create-file.error", fileName);
316 }
317
318 if (!exists()) {
319 try (FileContent content = getContent()) {
320 if (content != null) {
321 try (OutputStream ignored = content.getOutputStream()) {
322
323 }
324 }
325 }
326 }
327 } catch (final RuntimeException re) {
328 throw re;
329 } catch (final Exception e) {
330 throw new FileSystemException("vfs.provider/create-file.error", fileName, e);
331 }
332 }
333 }
334
335
336
337
338
339
340 @Override
341 public void createFolder() throws FileSystemException {
342 synchronized (fileSystem) {
343
344 if (getType().hasChildren()) {
345
346 return;
347 }
348 if (getType() != FileType.IMAGINARY) {
349 throw new FileSystemException("vfs.provider/create-folder-mismatched-type.error", fileName);
350 }
351
352
353
354
355
356
357
358 final FileObject parent = getParent();
359 if (parent != null) {
360 parent.createFolder();
361 }
362
363 try {
364
365 doCreateFolder();
366
367
368 handleCreate(FileType.FOLDER);
369 } catch (final RuntimeException re) {
370 throw re;
371 } catch (final Exception exc) {
372 throw new FileSystemException("vfs.provider/create-folder.error", fileName, exc);
373 }
374 }
375 }
376
377
378
379
380
381
382
383
384
385
386 @Override
387 public boolean delete() throws FileSystemException {
388 return delete(Selectors.SELECT_SELF) > 0;
389 }
390
391
392
393
394
395
396
397
398 @Override
399 public int delete(final FileSelector selector) throws FileSystemException {
400 int nuofDeleted = 0;
401
402
403
404
405
406
407 final ArrayList<FileObject> files = new ArrayList<>();
408 findFiles(selector, true, files);
409
410
411 for (final FileObject fileObject : files) {
412 final AbstractFileObject file = FileObjectUtils.getAbstractFileObject(fileObject);
413
414
415
416
417 if (file.getType().hasChildren() && file.getChildren().length != 0) {
418
419 continue;
420 }
421
422 if (file.deleteSelf()) {
423 nuofDeleted++;
424 }
425 }
426 return nuofDeleted;
427 }
428
429
430
431
432
433
434
435
436
437 @Override
438 public int deleteAll() throws FileSystemException {
439 return this.delete(Selectors.SELECT_ALL);
440 }
441
442
443
444
445
446
447
448 private boolean deleteSelf() throws FileSystemException {
449 synchronized (fileSystem) {
450
451
452
453
454
455
456 try {
457
458 doDelete();
459
460
461 handleDelete();
462 } catch (final RuntimeException re) {
463 throw re;
464 } catch (final Exception exc) {
465 throw new FileSystemException("vfs.provider/delete.error", exc, fileName);
466 }
467
468 return true;
469 }
470 }
471
472
473
474
475
476
477
478 private void detach() throws Exception {
479 synchronized (fileSystem) {
480 if (attached) {
481 try {
482 doDetach();
483 } finally {
484 attached = false;
485 setFileType(null);
486 parent = null;
487
488
489
490 removeChildrenCache();
491
492 }
493 }
494 }
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508
509 protected void doAttach() throws Exception {
510
511 }
512
513
514
515
516
517
518
519
520 protected FileContent doCreateFileContent() throws FileSystemException {
521 return new DefaultFileContent(this, getFileContentInfoFactory());
522 }
523
524
525
526
527
528
529
530
531
532
533
534 protected void doCreateFolder() throws Exception {
535 throw new FileSystemException("vfs.provider/create-folder-not-supported.error");
536 }
537
538
539
540
541
542
543
544
545
546
547
548
549 protected void doDelete() throws Exception {
550 throw new FileSystemException("vfs.provider/delete-not-supported.error");
551 }
552
553
554
555
556
557
558
559
560
561
562
563
564
565 protected void doDetach() throws Exception {
566
567 }
568
569
570
571
572
573
574
575
576
577
578
579 protected Map<String, Object> doGetAttributes() throws Exception {
580 return Collections.emptyMap();
581 }
582
583
584
585
586
587
588
589
590
591
592
593 protected Certificate[] doGetCertificates() throws Exception {
594 return null;
595 }
596
597
598
599
600
601
602
603
604 protected abstract long doGetContentSize() throws Exception;
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619 protected InputStream doGetInputStream() throws Exception {
620
621 return doGetInputStream(DEFAULT_BUFFER_SIZE);
622 }
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637 protected InputStream doGetInputStream(final int bufferSize) throws Exception {
638 throw new UnsupportedOperationException(DO_GET_INPUT_STREAM_INT);
639 }
640
641
642
643
644
645
646
647
648
649
650 protected long doGetLastModifiedTime() throws Exception {
651 throw new FileSystemException("vfs.provider/get-last-modified-not-supported.error");
652 }
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673 protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
674 throw new FileSystemException("vfs.provider/write-not-supported.error");
675 }
676
677
678
679
680
681
682
683
684
685
686
687 protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
688 throw new FileSystemException("vfs.provider/random-access-not-supported.error");
689 }
690
691
692
693
694
695
696
697
698 protected abstract FileType doGetType() throws Exception;
699
700
701
702
703
704
705
706
707
708
709
710 protected boolean doIsExecutable() throws Exception {
711 return false;
712 }
713
714
715
716
717
718
719
720
721
722
723
724 protected boolean doIsHidden() throws Exception {
725 return false;
726 }
727
728
729
730
731
732
733
734
735
736
737
738 protected boolean doIsReadable() throws Exception {
739 return true;
740 }
741
742
743
744
745
746
747
748
749
750 protected boolean doIsSameFile(final FileObject destFile) throws FileSystemException {
751 return false;
752 }
753
754
755
756
757
758
759
760
761
762
763
764
765 protected boolean doIsSymbolicLink() throws Exception {
766 return false;
767 }
768
769
770
771
772
773
774
775
776
777
778
779 protected boolean doIsWriteable() throws Exception {
780 return true;
781 }
782
783
784
785
786
787
788
789
790
791 protected abstract String[] doListChildren() throws Exception;
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809 protected FileObject[] doListChildrenResolved() throws Exception {
810 return null;
811 }
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826 protected void doRemoveAttribute(final String attrName) throws Exception {
827 throw new FileSystemException("vfs.provider/remove-attribute-not-supported.error");
828 }
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845 protected void doRename(final FileObject newFile) throws Exception {
846 throw new FileSystemException("vfs.provider/rename-not-supported.error");
847 }
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862 protected void doSetAttribute(final String attrName, final Object value) throws Exception {
863 throw new FileSystemException("vfs.provider/set-attribute-not-supported.error");
864 }
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882 protected boolean doSetExecutable(final boolean executable, final boolean ownerOnly) throws Exception {
883 return false;
884 }
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899 protected boolean doSetLastModifiedTime(final long modtime) throws Exception {
900 throw new FileSystemException("vfs.provider/set-last-modified-not-supported.error");
901 }
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919 protected boolean doSetReadable(final boolean readable, final boolean ownerOnly) throws Exception {
920 return false;
921 }
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936 protected boolean doSetWritable(final boolean writable, final boolean ownerOnly) throws Exception {
937 return false;
938 }
939
940
941
942
943
944
945 protected void endOutput() throws Exception {
946 if (getType() == FileType.IMAGINARY) {
947
948 handleCreate(FileType.FILE);
949 } else {
950
951 onChange();
952 }
953 }
954
955
956
957
958
959
960
961 @Override
962 public boolean exists() throws FileSystemException {
963 return getType() != FileType.IMAGINARY;
964 }
965
966 private FileName[] extractNames(final FileObject[] objects) {
967 if (objects == null) {
968 return null;
969 }
970 return Stream.of(objects).filter(Objects::nonNull).map(FileObject::getName).toArray(FileName[]::new);
971 }
972
973 @Override
974 protected void finalize() throws Throwable {
975 fileSystem.fileObjectDestroyed(this);
976
977 super.finalize();
978 }
979
980
981
982
983
984
985
986
987 @Override
988 public FileObject[] findFiles(final FileSelector selector) throws FileSystemException {
989 final List<FileObject> list = this.listFiles(selector);
990 return list == null ? null : list.toArray(EMPTY_ARRAY);
991 }
992
993
994
995
996
997
998
999
1000
1001 @Override
1002 public void findFiles(final FileSelector selector, final boolean depthwise, final List<FileObject> selected)
1003 throws FileSystemException {
1004 try {
1005 if (exists()) {
1006
1007 final DefaultFileSelectorInfo info = new DefaultFileSelectorInfo();
1008 info.setBaseFolder(this);
1009 info.setDepth(0);
1010 info.setFile(this);
1011 traverse(info, selector, depthwise, selected);
1012 }
1013 } catch (final Exception e) {
1014 throw new FileSystemException("vfs.provider/find-files.error", fileName, e);
1015 }
1016 }
1017
1018
1019
1020
1021
1022
1023 protected AFS getAbstractFileSystem() {
1024 return fileSystem;
1025 }
1026
1027
1028
1029
1030
1031
1032
1033
1034 @Override
1035 public FileObject getChild(final String name) throws FileSystemException {
1036
1037 final FileObject[] children = getChildren();
1038 for (final FileObject element : children) {
1039 final FileName child = element.getName();
1040 final String childBaseName = child.getBaseName();
1041
1042 if (childBaseName.equals(name) || UriParser.decode(childBaseName).equals(name)) {
1043 return resolveFile(child);
1044 }
1045 }
1046 return null;
1047 }
1048
1049
1050
1051
1052
1053
1054
1055 @Override
1056 public FileObject[] getChildren() throws FileSystemException {
1057 synchronized (fileSystem) {
1058
1059 if (!fileSystem.hasCapability(Capability.LIST_CHILDREN)) {
1060 throw new FileNotFolderException(fileName);
1061 }
1062
1063
1064
1065
1066
1067 attach();
1068
1069
1070 if (children != null) {
1071 return resolveFiles(children);
1072 }
1073
1074
1075 final FileObject[] childrenObjects;
1076 try {
1077 childrenObjects = doListChildrenResolved();
1078 children = extractNames(childrenObjects);
1079 } catch (final FileSystemException exc) {
1080
1081 throw exc;
1082 } catch (final Exception exc) {
1083 throw new FileSystemException("vfs.provider/list-children.error", exc, fileName);
1084 }
1085
1086 if (childrenObjects != null) {
1087 return childrenObjects;
1088 }
1089
1090
1091 final String[] files;
1092 try {
1093 files = doListChildren();
1094 } catch (final FileSystemException exc) {
1095
1096 throw exc;
1097 } catch (final Exception exc) {
1098 throw new FileSystemException("vfs.provider/list-children.error", exc, fileName);
1099 }
1100
1101 if (files == null) {
1102
1103
1104
1105 throw new FileNotFolderException(fileName);
1106 }
1107 if (files.length == 0) {
1108
1109 children = FileName.EMPTY_ARRAY;
1110 } else {
1111
1112 final FileName[] cache = new FileName[files.length];
1113 for (int i = 0; i < files.length; i++) {
1114 final String file = "./" + files[i];
1115 cache[i] = fileSystem.getFileSystemManager().resolveName(fileName, file, NameScope.CHILD);
1116 }
1117
1118
1119 children = cache;
1120 }
1121
1122 return resolveFiles(children);
1123 }
1124 }
1125
1126
1127
1128
1129
1130
1131
1132 @Override
1133 public FileContent getContent() throws FileSystemException {
1134 synchronized (fileSystem) {
1135 attach();
1136 if (content == null) {
1137 content = doCreateFileContent();
1138 }
1139 return content;
1140 }
1141 }
1142
1143
1144
1145
1146
1147
1148 protected FileContentInfoFactory getFileContentInfoFactory() {
1149 return fileSystem.getFileSystemManager().getFileContentInfoFactory();
1150 }
1151
1152
1153
1154
1155
1156 @Override
1157 public FileOperations getFileOperations() throws FileSystemException {
1158 if (operations == null) {
1159 operations = new DefaultFileOperations(this);
1160 }
1161
1162 return operations;
1163 }
1164
1165
1166
1167
1168
1169
1170 @Override
1171 public FileSystem getFileSystem() {
1172 return fileSystem;
1173 }
1174
1175
1176
1177
1178
1179
1180
1181 public InputStream getInputStream() throws FileSystemException {
1182 return getInputStream(DEFAULT_BUFFER_SIZE);
1183 }
1184
1185
1186
1187
1188
1189
1190
1191
1192 public InputStream getInputStream(final int bufferSize) throws FileSystemException {
1193
1194 try {
1195 return doGetInputStream(bufferSize);
1196 } catch (final org.apache.commons.vfs2.FileNotFoundException | FileNotFoundException exc) {
1197 throw new org.apache.commons.vfs2.FileNotFoundException(fileName, exc);
1198 } catch (final FileSystemException exc) {
1199 throw exc;
1200 } catch (final UnsupportedOperationException uoe) {
1201
1202
1203 if (DO_GET_INPUT_STREAM_INT.equals(uoe.getMessage())) {
1204 try {
1205
1206 return doGetInputStream();
1207 } catch (final Exception e) {
1208 if (e instanceof FileSystemException) {
1209 throw (FileSystemException) e;
1210 }
1211 throw new FileSystemException("vfs.provider/read.error", fileName, e);
1212 }
1213 }
1214 throw uoe;
1215 } catch (final Exception exc) {
1216 throw new FileSystemException("vfs.provider/read.error", fileName, exc);
1217 }
1218 }
1219
1220
1221
1222
1223
1224
1225 @Override
1226 public FileName getName() {
1227 return fileName;
1228 }
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238 public OutputStream getOutputStream() throws FileSystemException {
1239 return getOutputStream(false);
1240 }
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254 public OutputStream getOutputStream(final boolean bAppend) throws FileSystemException {
1255
1256
1257
1258
1259
1260
1261 if (bAppend && !fileSystem.hasCapability(Capability.APPEND_CONTENT)) {
1262 throw new FileSystemException("vfs.provider/write-append-not-supported.error", fileName);
1263 }
1264
1265 if (getType() == FileType.IMAGINARY) {
1266
1267 final FileObject parent = getParent();
1268 if (parent != null) {
1269 parent.createFolder();
1270 }
1271 }
1272
1273
1274 try {
1275 return doGetOutputStream(bAppend);
1276 } catch (final RuntimeException re) {
1277 throw re;
1278 } catch (final Exception exc) {
1279 throw new FileSystemException("vfs.provider/write.error", exc, fileName);
1280 }
1281 }
1282
1283
1284
1285
1286
1287
1288
1289 @Override
1290 public FileObject getParent() throws FileSystemException {
1291
1292 if (this.compareTo(fileSystem.getRoot()) == 0) {
1293 if (fileSystem.getParentLayer() == null) {
1294
1295 return null;
1296 }
1297
1298 return fileSystem.getParentLayer().getParent();
1299 }
1300
1301 synchronized (fileSystem) {
1302
1303 if (parent == null) {
1304 final FileName name = fileName.getParent();
1305 if (name == null) {
1306 return null;
1307 }
1308 parent = fileSystem.resolveFile(name);
1309 }
1310 return parent;
1311 }
1312 }
1313
1314
1315
1316
1317
1318
1319 @Override
1320 public String getPublicURIString() {
1321 return fileName.getFriendlyURI();
1322 }
1323
1324
1325
1326
1327
1328
1329
1330
1331 public RandomAccessContent getRandomAccessContent(final RandomAccessMode mode) throws FileSystemException {
1332
1333
1334
1335
1336 if (mode.requestRead()) {
1337 if (!fileSystem.hasCapability(Capability.RANDOM_ACCESS_READ)) {
1338 throw new FileSystemException("vfs.provider/random-access-read-not-supported.error");
1339 }
1340 if (!isReadable()) {
1341 throw new FileSystemException("vfs.provider/read-not-readable.error", fileName);
1342 }
1343 }
1344
1345 if (mode.requestWrite()) {
1346 if (!fileSystem.hasCapability(Capability.RANDOM_ACCESS_WRITE)) {
1347 throw new FileSystemException("vfs.provider/random-access-write-not-supported.error");
1348 }
1349 if (!isWriteable()) {
1350 throw new FileSystemException("vfs.provider/write-read-only.error", fileName);
1351 }
1352 }
1353
1354
1355 try {
1356 return doGetRandomAccessContent(mode);
1357 } catch (final Exception exc) {
1358 throw new FileSystemException("vfs.provider/random-access.error", fileName, exc);
1359 }
1360 }
1361
1362
1363
1364
1365
1366
1367
1368 @Override
1369 public FileType getType() throws FileSystemException {
1370 synchronized (fileSystem) {
1371 attach();
1372
1373
1374 try {
1375 if (type == null) {
1376 setFileType(doGetType());
1377 }
1378 if (type == null) {
1379 setFileType(FileType.IMAGINARY);
1380 }
1381 } catch (final Exception e) {
1382 throw new FileSystemException("vfs.provider/get-type.error", e, fileName);
1383 }
1384
1385 return type;
1386 }
1387 }
1388
1389
1390
1391
1392
1393
1394
1395 @Override
1396 public URL getURL() throws FileSystemException {
1397 try {
1398 return AccessController.doPrivileged((PrivilegedExceptionAction<URL>) () -> {
1399 final StringBuilder buf = new StringBuilder();
1400 final String scheme = UriParser.extractScheme(fileSystem.getContext().getFileSystemManager().getSchemes(), fileName.getURI(), buf);
1401 return new URL(scheme, "", -1, buf.toString(),
1402 new DefaultURLStreamHandler(fileSystem.getContext(), fileSystem.getFileSystemOptions()));
1403 });
1404 } catch (final PrivilegedActionException e) {
1405 throw new FileSystemException("vfs.provider/get-url.error", fileName, e.getException());
1406 }
1407 }
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417 protected void handleChanged() throws Exception {
1418
1419 fileSystem.fireFileChanged(this);
1420 }
1421
1422
1423
1424
1425
1426
1427
1428 protected void handleCreate(final FileType newType) throws Exception {
1429 synchronized (fileSystem) {
1430 if (attached) {
1431
1432 injectType(newType);
1433
1434 removeChildrenCache();
1435
1436
1437 onChange();
1438 }
1439
1440
1441 notifyParent(this.getName(), newType);
1442
1443
1444 fileSystem.fireFileCreated(this);
1445 }
1446 }
1447
1448
1449
1450
1451
1452
1453 protected void handleDelete() throws Exception {
1454 synchronized (fileSystem) {
1455 if (attached) {
1456
1457 injectType(FileType.IMAGINARY);
1458 removeChildrenCache();
1459
1460
1461 onChange();
1462 }
1463
1464
1465 notifyParent(this.getName(), FileType.IMAGINARY);
1466
1467
1468 fileSystem.fireFileDeleted(this);
1469 }
1470 }
1471
1472
1473
1474
1475
1476
1477
1478
1479 public void holdObject(final Object strongRef) {
1480 if (objects == null) {
1481 objects = new ArrayList<>(INITIAL_LIST_SIZE);
1482 }
1483 objects.add(strongRef);
1484 }
1485
1486
1487
1488
1489
1490
1491 protected void injectType(final FileType fileType) {
1492 setFileType(fileType);
1493 }
1494
1495
1496
1497
1498
1499
1500 @Override
1501 public boolean isAttached() {
1502 return attached;
1503 }
1504
1505
1506
1507
1508
1509
1510 @Override
1511 public boolean isContentOpen() {
1512 if (content == null) {
1513 return false;
1514 }
1515
1516 return content.isOpen();
1517 }
1518
1519
1520
1521
1522
1523
1524
1525 @Override
1526 public boolean isExecutable() throws FileSystemException {
1527 try {
1528 return exists() && doIsExecutable();
1529 } catch (final Exception exc) {
1530 throw new FileSystemException("vfs.provider/check-is-executable.error", fileName, exc);
1531 }
1532 }
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542 @Override
1543 public boolean isFile() throws FileSystemException {
1544
1545 return FileType.FILE.equals(this.getType());
1546 }
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556 @Override
1557 public boolean isFolder() throws FileSystemException {
1558
1559 return FileType.FOLDER.equals(this.getType());
1560 }
1561
1562
1563
1564
1565
1566
1567
1568 @Override
1569 public boolean isHidden() throws FileSystemException {
1570 try {
1571 return exists() && doIsHidden();
1572 } catch (final Exception exc) {
1573 throw new FileSystemException("vfs.provider/check-is-hidden.error", fileName, exc);
1574 }
1575 }
1576
1577
1578
1579
1580
1581
1582
1583 @Override
1584 public boolean isReadable() throws FileSystemException {
1585 try {
1586 return exists() && doIsReadable();
1587 } catch (final Exception exc) {
1588 throw new FileSystemException("vfs.provider/check-is-readable.error", fileName, exc);
1589 }
1590 }
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600 protected boolean isSameFile(final FileObject destFile) throws FileSystemException {
1601 attach();
1602 return doIsSameFile(destFile);
1603 }
1604
1605
1606
1607
1608
1609
1610
1611
1612 @Override
1613 public boolean isSymbolicLink() throws FileSystemException {
1614 try {
1615 return exists() && doIsSymbolicLink();
1616 } catch (final Exception exc) {
1617 throw new FileSystemException("vfs.provider/check-is-symbolic-link.error", fileName, exc);
1618 }
1619 }
1620
1621
1622
1623
1624
1625
1626
1627 @Override
1628 public boolean isWriteable() throws FileSystemException {
1629 try {
1630 if (exists()) {
1631 return doIsWriteable();
1632 }
1633 final FileObject parent = getParent();
1634 if (parent != null) {
1635 return parent.isWriteable();
1636 }
1637 return true;
1638 } catch (final Exception exc) {
1639 throw new FileSystemException("vfs.provider/check-is-writable.error", fileName, exc);
1640 }
1641 }
1642
1643
1644
1645
1646
1647
1648 @Override
1649 public Iterator<FileObject> iterator() {
1650 try {
1651 return listFiles(Selectors.SELECT_ALL).iterator();
1652 } catch (final FileSystemException e) {
1653 throw new IllegalStateException(e);
1654 }
1655 }
1656
1657
1658
1659
1660
1661
1662
1663
1664 public List<FileObject> listFiles(final FileSelector selector) throws FileSystemException {
1665 if (!exists() || selector == null) {
1666 return null;
1667 }
1668
1669 final ArrayList<FileObject> list = new ArrayList<>();
1670 this.findFiles(selector, true, list);
1671 return list;
1672 }
1673
1674
1675
1676
1677
1678
1679
1680 @Override
1681 public void moveTo(final FileObject destFile) throws FileSystemException {
1682 if (canRenameTo(destFile)) {
1683 if (!getParent().isWriteable()) {
1684 throw new FileSystemException("vfs.provider/rename-parent-read-only.error", getName(),
1685 getParent().getName());
1686 }
1687 } else if (!isWriteable()) {
1688 throw new FileSystemException("vfs.provider/rename-read-only.error", getName());
1689 }
1690
1691 if (destFile.exists() && !isSameFile(destFile)) {
1692 destFile.deleteAll();
1693
1694 }
1695
1696 if (canRenameTo(destFile)) {
1697
1698 try {
1699 attach();
1700
1701 final FileType srcType = getType();
1702
1703 doRename(destFile);
1704
1705 FileObjectUtils.getAbstractFileObject(destFile).handleCreate(srcType);
1706 destFile.close();
1707
1708 handleDelete();
1709 } catch (final RuntimeException re) {
1710 throw re;
1711 } catch (final Exception exc) {
1712 throw new FileSystemException("vfs.provider/rename.error", exc, getName(), destFile.getName());
1713 }
1714 } else {
1715
1716
1717 destFile.copyFrom(this, Selectors.SELECT_SELF);
1718
1719 if ((destFile.getType().hasContent()
1720 && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FILE)
1721 || destFile.getType().hasChildren()
1722 && destFile.getFileSystem().hasCapability(Capability.SET_LAST_MODIFIED_FOLDER))
1723 && fileSystem.hasCapability(Capability.GET_LAST_MODIFIED)) {
1724 destFile.getContent().setLastModifiedTime(this.getContent().getLastModifiedTime());
1725 }
1726
1727 deleteSelf();
1728 }
1729
1730 }
1731
1732
1733
1734
1735 protected void notifyAllStreamsClosed() {
1736
1737 }
1738
1739
1740
1741
1742
1743
1744
1745
1746 private void notifyParent(final FileName childName, final FileType newType) throws Exception {
1747 if (parent == null) {
1748 final FileName parentName = fileName.getParent();
1749 if (parentName != null) {
1750
1751 parent = fileSystem.getFileFromCache(parentName);
1752 }
1753 }
1754
1755 if (parent != null) {
1756 FileObjectUtils.getAbstractFileObject(parent).childrenChanged(childName, newType);
1757 }
1758 }
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768 protected void onChange() throws Exception {
1769
1770 }
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783 protected void onChildrenChanged(final FileName child, final FileType newType) throws Exception {
1784
1785 }
1786
1787
1788
1789
1790
1791
1792 @Override
1793 public void refresh() throws FileSystemException {
1794
1795 try {
1796 detach();
1797 } catch (final Exception e) {
1798 throw new FileSystemException("vfs.provider/resync.error", fileName, e);
1799 }
1800 }
1801
1802 private void removeChildrenCache() {
1803 children = null;
1804 }
1805
1806 private FileObject resolveFile(final FileName child) throws FileSystemException {
1807 return fileSystem.resolveFile(child);
1808 }
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818 @Override
1819 public FileObject resolveFile(final String path) throws FileSystemException {
1820 final FileName otherName = fileSystem.getFileSystemManager().resolveName(fileName, path);
1821 return fileSystem.resolveFile(otherName);
1822 }
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832 @Override
1833 public FileObject resolveFile(final String name, final NameScope scope) throws FileSystemException {
1834
1835 return fileSystem.resolveFile(fileSystem.getFileSystemManager().resolveName(fileName, name, scope));
1836 }
1837
1838 private FileObject[] resolveFiles(final FileName[] children) throws FileSystemException {
1839 if (children == null) {
1840 return null;
1841 }
1842
1843 final FileObject[] objects = new FileObject[children.length];
1844 for (int iterChildren = 0; iterChildren < children.length; iterChildren++) {
1845 objects[iterChildren] = resolveFile(children[iterChildren]);
1846 }
1847
1848 return objects;
1849 }
1850
1851 @Override
1852 public boolean setExecutable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
1853 try {
1854 return exists() && doSetExecutable(readable, ownerOnly);
1855 } catch (final Exception exc) {
1856 throw new FileSystemException("vfs.provider/set-executable.error", fileName, exc);
1857 }
1858 }
1859
1860 private void setFileType(final FileType type) {
1861 if (type != null && type != FileType.IMAGINARY) {
1862 Uncheck.run(() -> fileName.setType(type));
1863 }
1864 this.type = type;
1865 }
1866
1867 @Override
1868 public boolean setReadable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
1869 try {
1870 return exists() && doSetReadable(readable, ownerOnly);
1871 } catch (final Exception exc) {
1872 throw new FileSystemException("vfs.provider/set-readable.error", fileName, exc);
1873 }
1874 }
1875
1876 @Override
1877 public boolean setWritable(final boolean readable, final boolean ownerOnly) throws FileSystemException {
1878 try {
1879 return exists() && doSetWritable(readable, ownerOnly);
1880 } catch (final Exception exc) {
1881 throw new FileSystemException("vfs.provider/set-writable.error", fileName, exc);
1882 }
1883 }
1884
1885
1886
1887
1888
1889
1890 @Override
1891 public String toString() {
1892 return fileName.getURI();
1893 }
1894 }