1 19 20 package org.openide.filesystems; 21 22 import java.io.FileNotFoundException ; 23 import java.io.IOException ; 24 import java.io.InputStream ; 25 import java.io.OutputStream ; 26 import java.io.Serializable ; 27 import java.lang.ref.Reference ; 28 import java.lang.ref.WeakReference ; 29 import java.util.Date ; 30 import java.util.Enumeration ; 31 import org.openide.util.Enumerations; 32 33 36 40 final class AbstractFileObject extends AbstractFolder { 41 42 static final long serialVersionUID = -2343651324897646809L; 43 44 45 private static final char EXT_SEP = '.'; 46 47 48 private static final char PATH_SEP = '/'; 49 50 51 private Reference <FileLock> lock; 52 53 54 private Boolean folder; 55 56 57 private Date lastModified = lastModified(); 58 59 65 public AbstractFileObject(AbstractFileSystem fs, AbstractFileObject parent, String name) { 66 super(fs, parent, name); 67 } 68 69 70 private AbstractFileSystem getAbstractFileSystem() { 71 return (AbstractFileSystem) getFileSystem(); 72 } 73 74 76 private AbstractFileObject getAbstractChild(String name) { 77 return (AbstractFileObject) getChild(name); 78 } 79 80 84 88 protected final String [] list() { 89 return getAbstractFileSystem().list.children(getPath()); 90 } 91 92 96 protected final AbstractFolder createFile(String name) { 97 return getAbstractFileSystem().createFileObject(this, name); 98 } 99 100 104 107 public boolean isFolder() { 108 if (folder == null) { 109 if ((parent == null) || getAbstractFileSystem().info.folder(getPath())) { 110 folder = Boolean.TRUE; 111 112 return true; 113 } else { 114 folder = Boolean.FALSE; 115 116 return false; 117 } 118 } else { 119 return folder.booleanValue(); 120 } 121 } 122 123 127 public final boolean isData() { 128 return !isFolder(); 129 } 130 131 135 public Date lastModified() { 136 if ((lastModified == null) || !getAbstractFileSystem().isLastModifiedCacheEnabled()) { 137 String path = getPath(); 138 AbstractFileSystem.Info i = getAbstractFileSystem().info; 139 lastModified = i.lastModified(path); 140 assert lastModified != null : "Null lastModified from " + i.getClass().getName() + " on " + path; 141 } 142 143 return lastModified; 144 } 145 146 @Deprecated public boolean isReadOnly() { 148 AbstractFileSystem fs = getAbstractFileSystem(); 149 150 return fs.isReadOnly() || fs.info.readOnly(getPath()); 151 } 152 153 public String getMIMEType() { 154 String retVal = getAbstractFileSystem().info.mimeType(getPath()); 155 156 if (retVal == null) { 157 retVal = FileUtil.getMIMETypeOrDefault(this); 158 } 159 160 return retVal; 161 } 162 163 167 public long getSize() { 168 return getAbstractFileSystem().info.size(getPath()); 169 } 170 171 176 public InputStream getInputStream() throws FileNotFoundException { 177 return StreamPool.createInputStream(this); 178 } 179 180 186 public OutputStream getOutputStream(FileLock lock) 187 throws IOException { 188 return getOutputStream(lock, true); 189 } 190 191 192 synchronized OutputStream getOutputStream(FileLock lock, boolean fireFileChanged) 193 throws IOException { 194 FileSystem fs = getAbstractFileSystem(); 195 196 if (fs.isReadOnly()) { 197 FSException.io("EXC_FSisRO", fs.getDisplayName()); } 199 200 if (isReadOnly()) { 201 FSException.io("EXC_FisRO", name, fs.getDisplayName()); } 203 204 testLock(lock); 205 206 return StreamPool.createOutputStream(this, fireFileChanged); 207 } 208 209 213 public synchronized FileLock lock() throws IOException { 214 if (lock != null) { 215 FileLock f = lock.get(); 216 217 if (f != null) { 218 throw new FileAlreadyLockedException(); 220 } 221 } 222 223 getAbstractFileSystem().info.lock(getPath()); 224 225 FileLock l = new AfLock(); 226 lock = new WeakReference <FileLock>(l); 227 228 return l; 231 } 232 233 235 void unlock(FileLock fLock) { 236 FileLock currentLock = null; 237 238 synchronized(this) { 239 if (lock != null) { 240 currentLock = lock.get(); 241 } 242 243 if (currentLock == fLock) { 244 lastModified = null; 245 lock = null; 247 } 248 } 249 getAbstractFileSystem().info.unlock(getPath()); 250 251 if (isValid()) { 252 lastModified(); 253 } 254 } 255 256 259 private void testLock(FileLock l) throws IOException { 260 if (lock == null) { 261 FSException.io("EXC_InvalidLock", l, getPath(), getAbstractFileSystem().getDisplayName(), lock); } 263 264 if (lock.get() != l) { 265 FSException.io("EXC_InvalidLock", l, getPath(), getAbstractFileSystem().getDisplayName(), lock.get()); } 267 } 268 269 @Deprecated public void setImportant(boolean b) { 271 getAbstractFileSystem().markImportant(getPath(), b); 272 } 273 274 278 public Object getAttribute(String attrName) { 279 return getAttribute(attrName, getPath()); 280 } 281 282 283 final Object getAttribute(String attrName, String path) { 284 return getAbstractFileSystem().attr.readAttribute(path, attrName); 285 } 286 287 292 public void setAttribute(String attrName, Object value) 293 throws IOException { 294 setAttribute(attrName, value, true); 295 } 296 297 300 void setAttribute(String attrName, Object value, boolean fire) 301 throws IOException { 302 Object oldValue = null; 303 304 if (fire) { 308 oldValue = getAttribute(attrName); 309 } 310 311 getAbstractFileSystem().attr.writeAttribute(getPath(), attrName, value); 312 313 if (fire && (oldValue != value) && hasAtLeastOneListeners()) { 314 fileAttributeChanged0(new FileAttributeEvent(this, attrName, oldValue, value)); 315 } 316 } 317 318 321 public Enumeration <String > getAttributes() { 322 return getAttributes(getPath()); 323 } 324 325 final Enumeration <String > getAttributes(String path) { 326 return getAbstractFileSystem().attr.attributes(path); 327 } 328 329 334 protected final Reference <AbstractFolder> createReference(AbstractFolder fo) { 335 return (getAbstractFileSystem().createReference(fo)); 336 } 337 338 345 public FileObject createFolder(String name) throws IOException { 346 AbstractFileObject fo; 347 348 try { 349 getFileSystem().beginAtomicAction(); 350 351 synchronized (this) { 352 AbstractFileSystem fs = getAbstractFileSystem(); 353 354 if (fs.isReadOnly()) { 355 FSException.io("EXC_FSisRO", fs.getDisplayName()); } 357 358 if (isReadOnly()) { 359 FSException.io("EXC_FisRO", name, fs.getDisplayName()); } 361 362 if (!isFolder()) { 363 FSException.io("EXC_FoNotFolder", name, getPath(), fs.getDisplayName()); } 365 366 getAbstractFileSystem().change.createFolder(getPath() + PATH_SEP + name); 367 registerChild(name); 368 fo = getAbstractChild(name); 369 370 if (fo == null) { 371 throw new FileStateInvalidException( 373 FileSystem.getString("EXC_ApplicationCreateError", getPath(), name) 374 ); 375 } 376 377 if (hasListeners()) { 378 fileCreated0(new FileEvent(this, fo), false); 379 } 380 } 381 } finally { 382 getFileSystem().finishAtomicAction(); 383 } 384 385 return fo; 386 } 387 388 397 public FileObject createData(String name, String ext) 398 throws IOException { 399 if (name.indexOf(PATH_SEP) != -1) { 400 throw new IllegalArgumentException ("Use FileUtil.createData() instead!"); } 402 403 String fName = null; 404 try { 405 getFileSystem().beginAtomicAction(); 406 String n = null; 407 synchronized (this) { 408 AbstractFileSystem fs = getAbstractFileSystem(); 409 410 if (fs.isReadOnly()) { 411 FSException.io("EXC_FSisRO", fs.getDisplayName()); } 413 414 if (isReadOnly()) { 415 FSException.io("EXC_FisRO", name, fs.getDisplayName()); } 417 418 n = ((ext == null) || "".equals(ext)) ? name : (name + EXT_SEP + ext); 420 if (!isFolder()) { 421 FSException.io("EXC_FoNotFolder", n, getPath(), fs.getDisplayName()); } 423 424 fName = getPath() + PATH_SEP + n; 425 } 426 getAbstractFileSystem().change.createData(fName); 428 429 synchronized (this) { 430 registerChild(n); 431 432 AbstractFileObject fo = getAbstractChild(n); 433 434 if (fo == null) { 435 throw new FileStateInvalidException( 437 FileSystem.getString("EXC_ApplicationCreateError", getPath(), n) 438 ); 439 } 440 441 if (hasListeners()) { 442 fileCreated0(new FileEvent(this, fo), true); 443 } 444 445 return fo; 446 } 447 } finally { 448 getFileSystem().finishAtomicAction(); 449 } 450 } 451 452 463 public void rename(FileLock lock, String name, String ext) 464 throws IOException { 465 if (parent == null) { 466 FSException.io("EXC_CannotRenameRoot", getAbstractFileSystem().getDisplayName()); } 468 469 if ( 470 (name.indexOf('/') != -1) || ((ext != null) && (ext.indexOf('/') != -1)) || (name.indexOf('\\') != -1) || 471 ((ext != null) && (ext.indexOf('\\') != -1)) 472 ) { 473 FSException.io("EXC_CannotRename", getPath(), getAbstractFileSystem().getDisplayName(), name + "." + ext); } 475 476 try { 477 getFileSystem().beginAtomicAction(); 478 479 String newFullName = null; 480 String oldFullName = null; 481 482 synchronized (parent) { 483 testLock(lock); 485 486 if (isData()) { 487 if (ext != null) { 488 name = name + EXT_SEP + ext; 489 } 490 } 491 492 newFullName = parent.isRoot() ? name : parent.getPath() + PATH_SEP + name; 493 oldFullName = getPath(); 494 495 if (isReadOnly()) { 496 FSException.io( 497 "EXC_CannotRename", getPath(), getAbstractFileSystem().getDisplayName(), newFullName 498 ); } 500 501 if (getFileSystem().isReadOnly()) { 502 FSException.io("EXC_FSisRO", getAbstractFileSystem().getDisplayName()); } 504 505 String on = getName(); 506 String oe = getExt(); 507 508 getAbstractFileSystem().change.rename(oldFullName, newFullName); 509 510 String oldName = this.name; 511 this.name = name; 512 513 519 parent.refresh(name, oldName); 520 521 if (hasAtLeastOneListeners()) { 522 fileRenamed0(new FileRenameEvent(this, on, oe)); 523 } 524 } 525 526 getAbstractFileSystem().attr.renameAttributes(oldFullName, newFullName); 527 } finally { 528 getFileSystem().finishAtomicAction(); 529 } 530 } 531 532 538 void handleDelete(FileLock lock) throws IOException { 539 if (parent == null) { 540 FSException.io("EXC_CannotDeleteRoot", getAbstractFileSystem().getDisplayName()); } 542 543 String fullName; 544 545 try { 546 getFileSystem().beginAtomicAction(); 547 548 synchronized (parent) { 549 testLock(lock); 550 551 fullName = getPath(); 552 553 try { 554 getAbstractFileSystem().change.delete(fullName); 555 } catch (IOException ex) { 556 StreamPool p = StreamPool.find(this); 557 558 if (p != null) { 559 p.annotate(ex); 560 } 561 562 throw ex; 563 } 564 565 String n = name; 566 validFlag = false; 567 568 parent.refresh(null, n, true); 569 } 570 571 getAbstractFileSystem().attr.deleteAttributes(fullName); 572 573 if (hasAtLeastOneListeners()) { 574 fileDeleted0(new FileEvent(this)); 575 } 576 } finally { 577 getFileSystem().finishAtomicAction(); 578 } 579 } 580 581 585 594 public FileObject copy(FileObject target, String name, String ext) 595 throws IOException { 596 AbstractFileSystem.Transfer from = getAbstractFileSystem().transfer; 597 598 if ((from == null) || !(target instanceof AbstractFileObject)) { 599 return super.copy(target, name, ext); 600 } 601 602 AbstractFileObject abstractTarget = (AbstractFileObject) target; 603 AbstractFileSystem abstractFS = abstractTarget.getAbstractFileSystem(); 604 AbstractFileSystem.Transfer to = abstractFS.transfer; 605 606 if (to != null) { 607 try { 608 getFileSystem().beginAtomicAction(); 609 610 synchronized (abstractTarget) { 611 if (abstractFS.isReadOnly()) { 613 FSException.io("EXC_FSisRO", abstractFS.getDisplayName()); } 615 616 if (!target.canWrite()) { 617 FSException.io("EXC_FisRO", target.getPath(), abstractFS.getDisplayName()); } 619 620 String n = "".equals(ext) ? name : (name + EXT_SEP + ext); 622 if (from.copy(getPath(), to, target.getPath() + PATH_SEP + n)) { 623 abstractTarget.registerChild(n); 625 626 AbstractFileObject fo = abstractTarget.getAbstractChild(n); 627 628 if (fo == null) { 629 throw new FileStateInvalidException( 631 FileSystem.getString("EXC_ApplicationCreateError", abstractTarget.getPath(), n) 632 ); 633 } 634 635 if (abstractTarget.hasListeners()) { 636 abstractTarget.fileCreated0(new FileEvent(abstractTarget, fo), true); 637 } 638 639 return fo; 640 } 641 } 642 } finally { 643 getFileSystem().finishAtomicAction(); 644 } 645 } 646 647 return super.copy(target, name, ext); 648 } 649 650 660 public FileObject move(FileLock lock, FileObject target, String name, String ext) 661 throws IOException { 662 AbstractFileSystem fs = getAbstractFileSystem(); 663 664 if (parent == null) { 665 FSException.io("EXC_CannotDeleteRoot", fs.getDisplayName()); } 667 668 AbstractFileSystem.Transfer from = getAbstractFileSystem().transfer; 669 670 if ((from == null) || !(target instanceof AbstractFileObject)) { 671 return super.move(lock, target, name, ext); 672 } 673 674 AbstractFileObject abstractTarget = (AbstractFileObject) target; 675 AbstractFileSystem abstractFS = abstractTarget.getAbstractFileSystem(); 676 AbstractFileSystem.Transfer to = abstractFS.transfer; 677 678 if (to != null) { 679 try { 680 getFileSystem().beginAtomicAction(); 681 682 synchronized (parent) { 683 testLock(lock); 684 685 if (abstractFS.isReadOnly()) { 686 FSException.io("EXC_FSisRO", abstractFS.getDisplayName()); } 688 689 if (!target.canWrite()) { 690 FSException.io("EXC_FisRO", target.getPath(), abstractFS.getDisplayName()); } 692 693 String n = "".equals(ext) ? name : (name + EXT_SEP + ext); String fullName = getPath(); 695 696 if (from.move(fullName, to, target.getPath() + PATH_SEP + n)) { 697 String oldN = name; 699 validFlag = false; 700 701 parent.refresh(null, oldN); 703 704 abstractTarget.registerChild(n); 710 711 AbstractFileObject fo = abstractTarget.getAbstractChild(n); 712 713 if (fo == null) { 714 throw new FileStateInvalidException( 716 FileSystem.getString("EXC_ApplicationCreateError", abstractTarget.getPath(), n) 717 ); 718 } 719 720 if (hasAtLeastOneListeners()) { 721 fileDeleted0(new FileEvent(this)); 722 } 723 724 if (abstractTarget.hasListeners()) { 725 abstractTarget.fileCreated0(new FileEvent(abstractTarget, fo), true); 726 } 727 728 return fo; 729 } 730 } 731 } finally { 732 getFileSystem().finishAtomicAction(); 733 } 734 } 735 736 return super.move(lock, target, name, ext); 737 } 738 739 744 public boolean isVirtual() { 745 return getAbstractFileSystem().checkVirtual(getPath()); 746 } 747 748 754 protected void refresh(String added, String removed, boolean fire, boolean expected) { 755 this.refresh(added, removed, fire, expected, null); 756 } 757 758 765 protected void refresh(String added, String removed, boolean fire, boolean expected, String [] list) { 766 FileEvent ev = null; 767 boolean refreshParent = false; 768 769 try { 770 getFileSystem().beginAtomicAction(); 771 772 if (isFolder()) { 773 super.refresh(added, removed, fire, expected, list); 774 } else { 775 StreamPool strPool = StreamPool.find(this); 776 777 778 if ((strPool != null) && strPool.isOutputStreamOpen()) { 779 return; 780 } 781 782 synchronized (this) { 783 Date l = null; 785 786 if (lastModified == null) { 787 lastModified = l = getAbstractFileSystem().info.lastModified(getPath()); 788 789 return; 790 } else { 791 l = getAbstractFileSystem().info.lastModified(getPath()); 792 } 793 794 799 800 if (Math.abs(lastModified.getTime() - l.getTime()) != 0) { 806 812 lastModified = l; 813 814 if (fire && hasAtLeastOneListeners()) { 815 ev = new FileEvent(this, this, expected); 816 } 817 818 if (l.getTime() == 0) { 819 if (validFlag) { 820 validFlag = false; 821 822 if (ev != null) { 823 fileDeleted0(ev); 824 } 825 826 refreshParent = true; 827 } 828 } else if (ev != null) { 829 fileChanged0(ev); 830 } 831 } 832 } 833 } 834 835 if (refreshParent && (parent.getFileObject(getName(), getExt()) != null)) { 836 parent.refreshFolder(null, this.getNameExt(), fire, expected, null); 837 } 838 } finally { 839 getFileSystem().finishAtomicAction(); 840 } 841 842 return; 844 } 845 846 851 protected void outputStreamClosed(boolean fireFileChanged) { 852 synchronized (this) { 853 lastModified = null; 854 lastModified(); 855 } 856 857 super.outputStreamClosed(fireFileChanged); 858 } 859 860 public boolean canWrite() { 862 AbstractFileSystem fs = getAbstractFileSystem(); 863 864 return fs.canWrite(getPath()); 865 } 866 867 public boolean canRead() { 869 AbstractFileSystem fs = getAbstractFileSystem(); 870 871 return fs.canRead(getPath()); 872 } 873 874 final boolean superCanWrite() { 876 return super.canWrite(); 877 } 878 879 final boolean superCanRead() { 881 return super.canRead(); 882 } 883 884 886 private class AfLock extends FileLock { 887 AfLock() { 888 } 889 890 public void releaseLock() { 891 if (this.isValid()) { 892 super.releaseLock(); 893 unlock(this); 894 } 895 } 896 } 897 898 static final class Invalid extends FileObject { 902 static final long serialVersionUID = -4558997829579415276L; 903 904 905 private static final Invalid ROOT = new Invalid(""); 907 908 private String name; 909 private String fileSystemName; 910 911 914 public Invalid(String name) { 915 int i = name.lastIndexOf('/') + 1; 916 this.name = ((i == 0) || (i == name.length())) ? name : name.substring(i); 917 } 918 919 923 public Invalid(String fs, String name) { 924 this(name); 925 fileSystemName = fs; 926 } 927 928 933 public String getName() { 934 int i = name.lastIndexOf('.'); 935 936 return (i <= 0) ? name : name.substring(0, i); 937 } 938 939 945 public String getExt() { 946 int i = name.lastIndexOf('.') + 1; 947 948 return ((i <= 1) || (i == name.length())) ? "" : name.substring(i); } 950 951 953 public FileSystem getFileSystem() throws FileStateInvalidException { 954 throw new FileStateInvalidException(null, name + "[" + fileSystemName + "]"); } 956 957 961 965 public boolean isRoot() { 966 return this == ROOT; 967 } 968 969 972 public boolean isFolder() { 973 return this == ROOT; 974 } 975 976 980 public Date lastModified() { 981 return new Date (); 982 } 983 984 988 public boolean isData() { 989 return false; 990 } 991 992 @Deprecated public boolean isReadOnly() { 994 return false; 995 } 996 997 1002 public boolean isValid() { 1003 return false; 1004 } 1005 1006 1014 public String getMIMEType() { 1015 return "content/unknown"; } 1017 1018 1022 public long getSize() { 1023 return 0; 1024 } 1025 1026 1030 public InputStream getInputStream() throws FileNotFoundException { 1031 throw new FileNotFoundException (); 1032 } 1033 1034 1040 public synchronized OutputStream getOutputStream(FileLock lock) 1041 throws IOException { 1042 throw new IOException (); 1043 } 1044 1045 1049 public synchronized FileLock lock() throws IOException { 1050 throw new IOException (); 1051 } 1052 1053 @Deprecated public void setImportant(boolean b) { 1055 } 1056 1057 1061 public Object getAttribute(String attrName) { 1062 return null; 1063 } 1064 1065 1070 public void setAttribute(String attrName, Object value) 1071 throws IOException { 1072 throw new IOException (); 1073 } 1074 1075 1078 public Enumeration <String > getAttributes() { 1079 return Enumerations.empty(); 1080 } 1081 1082 1089 public synchronized FileObject createFolder(String name) 1090 throws IOException { 1091 throw new IOException (); 1092 } 1093 1094 1103 public synchronized FileObject createData(String name, String ext) 1104 throws IOException { 1105 throw new IOException (); 1106 } 1107 1108 1119 public void rename(FileLock lock, String name, String ext) 1120 throws IOException { 1121 throw new IOException (); 1122 } 1123 1124 1130 public void delete(FileLock lock) throws IOException { 1131 throw new IOException (); 1132 } 1133 1134 1138 1143 public FileObject getParent() { 1144 return (this == ROOT) ? null : ROOT; 1145 } 1146 1147 1155 public synchronized FileObject[] getChildren() { 1156 return new FileObject[0]; 1157 } 1158 1159 1168 public synchronized FileObject getFileObject(String name, String ext) { 1169 return null; 1170 } 1171 1172 1174 public void refresh() { 1175 } 1176 1177 1181 1184 public void addFileChangeListener(FileChangeListener fcl) { 1185 } 1186 1187 1190 public void removeFileChangeListener(FileChangeListener fcl) { 1191 } 1192 } 1193 1195 1198 @Deprecated 1199 static final class Replace extends Object implements Serializable { 1200 1201 static final long serialVersionUID = -8543432135435542113L; 1202 private String fsName; 1203 private String fileName; 1204 1205 1207 public Replace(String fsName, String fileName) { 1208 this.fsName = fsName; 1209 this.fileName = fileName; 1210 } 1211 1212 1214 public Object readResolve() { 1215 Repository rep = ExternalUtil.getRepository(); 1216 @SuppressWarnings ("deprecation") FileSystem fs = rep.findFileSystem(fsName); 1218 FileObject fo = null; 1219 1220 if (fs != null) { 1221 fo = fs.findResource(fileName); 1223 } 1224 1225 if (fo == null) { 1226 return new Invalid(fsName, fileName); 1228 } 1229 1230 return fo; 1231 } 1232 } 1233 } 1235 | Popular Tags |