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