1 19 20 package org.openide.loaders; 21 22 23 import java.beans.PropertyVetoException ; 24 import java.io.*; 25 import java.lang.ref.WeakReference ; 26 import java.util.*; 27 import java.util.logging.*; 28 import javax.swing.event.*; 29 import org.openide.filesystems.*; 30 import org.openide.nodes.*; 31 import org.openide.util.*; 32 33 39 public class MultiDataObject extends DataObject { 40 41 static final long serialVersionUID = -7750146802134210308L; 42 43 45 private static final Object cookieSetLock = new Object (); 46 47 48 private static final Object secondaryCreationLock = new Object (); 49 50 51 private static final RequestProcessor firingProcessor = 52 new RequestProcessor( "MDO PropertyChange processor"); 53 54 55 private static final RequestProcessor delayProcessor = 56 new RequestProcessor( "MDO Firing delayer"); 57 58 private RequestProcessor.Task delayedPropFilesTask; 59 60 private static final Object delayedPropFilesLock = new Object (); 61 62 static final Logger ERR = Logger.getLogger(MultiDataObject.class.getName()); 63 64 65 private Entry primary; 66 67 68 private HashMap<FileObject,Entry> secondary; 69 70 71 private CookieSet cookieSet; 72 73 74 boolean checked = false; 75 76 81 public MultiDataObject(FileObject fo, MultiFileLoader loader) throws DataObjectExistsException { 82 super(fo, loader); 83 primary = createPrimaryEntry (this, getPrimaryFile ()); 84 } 85 86 94 @Deprecated 95 MultiDataObject(FileObject fo, DataLoader loader) throws DataObjectExistsException { 96 super(fo, loader); 97 primary = createPrimaryEntry (this, getPrimaryFile ()); 98 } 99 100 105 public final MultiFileLoader getMultiFileLoader () { 106 DataLoader loader = getLoader (); 107 108 if (!(loader instanceof MultiFileLoader)) 109 return null; 110 111 return (MultiFileLoader)loader; 112 } 113 114 @Override 115 public Set<FileObject> files () { 116 return new FilesSet (this); 118 } 119 120 123 public boolean isDeleteAllowed() { 124 return !getPrimaryFile ().isReadOnly () && !existReadOnlySecondary(); 125 } 126 127 private boolean existReadOnlySecondary() { 128 synchronized ( synchObjectSecondary() ) { 129 for (FileObject f : getSecondary().keySet()) { 130 if (f.isReadOnly()) { 131 return true; 132 } 133 } 134 } 135 return false; 136 } 137 138 141 private Map<FileObject,Entry> checkSecondary () { 142 if (! checked) { 144 checkFiles (this); 145 checked = true; 146 } 147 return getSecondary(); 148 } 149 150 153 Map<FileObject,Entry> getSecondary() { 154 synchronized (secondaryCreationLock) { 155 if (secondary == null) { 156 secondary = new HashMap<FileObject,Entry>(4); 157 } 158 if (ERR.isLoggable(Level.FINE)) { 159 ERR.fine("getSecondary for " + this + " is " + secondary); } 161 return secondary; 162 } 163 } 164 165 168 public boolean isCopyAllowed() { 169 return true; 170 } 171 172 175 public boolean isMoveAllowed() { 176 return !getPrimaryFile ().isReadOnly () && !existReadOnlySecondary(); 177 } 178 179 182 public boolean isRenameAllowed () { 183 return !getPrimaryFile ().isReadOnly () && !existReadOnlySecondary(); 184 } 185 186 189 public HelpCtx getHelpCtx() { 190 return HelpCtx.DEFAULT_HELP; 191 } 192 193 197 Object synchObjectSecondary() { 198 Object lock = checkSecondary(); 199 if (lock == null) throw new IllegalStateException ("checkSecondary was null from " + this); return checkSecondary(); 201 } 202 203 208 protected Node createNodeDelegate () { 209 DataNode dataNode = (DataNode) super.createNodeDelegate (); 210 return dataNode; 211 } 212 213 216 protected final void addSecondaryEntry (Entry fe) { 217 synchronized ( getSecondary() ) { 218 getSecondary().put (fe.getFile (), fe); 219 if (ERR.isLoggable(Level.FINE)) { 220 ERR.fine("addSecondaryEntry: " + fe + " for " + this); } 222 } 223 224 FolderList l = getFolderList(); 228 if (l == null) { 229 firePropertyChangeLater (PROP_FILES, null, null); 230 } else { if (l.isCreated()) { 232 firePropertyChangeLater (PROP_FILES, null, null); 233 } else { 234 firePropFilesAfterFinishing(); 235 } 236 } 237 } 238 239 242 private FolderList getFolderList() { 243 FileObject parent = primary.file.getParent(); 244 if (parent != null) { 245 return FolderList.find(parent, false); 246 } 247 return null; 248 } 249 250 253 protected final void removeSecondaryEntry (Entry fe) { 254 synchronized (getSecondary()) { 255 getSecondary().remove (fe.getFile ()); 256 if (ERR.isLoggable(Level.FINE)) { 257 ERR.fine("removeSecondaryEntry: " + fe + " for " + this); } 259 } 260 261 firePropertyChangeLater (PROP_FILES, null, null); 262 updateFilesInCookieSet(); 263 264 if (fe.isImportant ()) { 265 checkConsistency(this); 266 } 267 } 268 269 272 final void markSecondaryEntriesRecognized (DataLoader.RecognizedFiles recognized) { 273 synchronized (getSecondary()) { 274 for (FileObject fo : getSecondary().keySet()) { 275 recognized.markRecognized (fo); 276 } 277 } 278 } 279 280 281 293 protected final Entry registerEntry (FileObject fo) { 294 synchronized (getSecondary()) { 295 if (fo == null) { 296 return primary; 298 } 299 if (fo.equals (getPrimaryFile ())) { 300 return primary; 301 } 302 303 Entry e = getSecondary().get(fo); 304 if (e != null) { 305 return e; 306 } 307 308 e = createSecondaryEntry (this, fo); 310 addSecondaryEntry (e); 311 312 return e; 313 } 314 } 315 316 319 final void removeFile (FileObject fo) { 320 synchronized (getSecondary()) { 321 Entry e = getSecondary().get(fo); 322 if (e != null) { 323 removeSecondaryEntry (e); 324 } 325 } 326 } 327 328 331 public final Entry getPrimaryEntry () { 332 return primary; 333 } 334 335 338 public final Set<Entry> secondaryEntries () { 339 synchronized ( synchObjectSecondary() ) { 340 removeAllInvalid (); 341 342 return new HashSet<Entry>(getSecondary().values()); 343 } 344 } 345 346 351 public final Entry findSecondaryEntry (FileObject fo) { 352 Entry e; 353 synchronized ( synchObjectSecondary() ) { 354 removeAllInvalid (); 355 e = getSecondary().get(fo); 356 } 357 return e; 358 } 359 360 363 private void removeAllInvalid () { 364 if (ERR.isLoggable(Level.FINE)) { 365 ERR.fine("removeAllInvalid, started " + this); } 367 Iterator it = checkSecondary ().entrySet ().iterator (); 368 while (it.hasNext ()) { 369 Map.Entry e = (Map.Entry)it.next (); 370 FileObject fo = (FileObject)e.getKey (); 371 if (!fo.isValid ()) { 372 it.remove (); 373 if (ERR.isLoggable(Level.FINE)) { 374 ERR.fine("removeAllInvalid, removed: " + fo + " for " + this); } 376 firePropertyChangeLater (PROP_FILES, null, null); 377 } 378 } 379 if (ERR.isLoggable(Level.FINE)) { 380 ERR.fine("removeAllInvalid, finished " + this); } 382 } 383 384 385 387 393 protected FileLock takePrimaryFileLock () throws IOException { 394 return getPrimaryEntry ().takeLock (); 395 } 396 397 403 private String existInFolder(FileObject fo, FileObject folder) { 404 if (fo.isFolder () && isMergingFolders (fo, folder)) 406 return ""; 408 String orig = fo.getName (); 409 String name = FileUtil.findFreeFileName( 410 folder, orig, fo.getExt () 411 ); 412 if (name.length () <= orig.length ()) { 413 return ""; } else { 415 return name.substring (orig.length ()); 416 } 417 } 418 419 426 boolean isMergingFolders(FileObject who, FileObject targetFolder) { 427 return false; 428 } 429 430 437 protected DataObject handleCopy (DataFolder df) throws IOException { 438 FileObject fo; 439 440 String suffix = existInFolder( 441 getPrimaryEntry().getFile(), 442 df.getPrimaryFile () 443 ); 444 if (suffix == null) 445 throw new org.openide.util.UserCancelException(); 446 447 Iterator it = secondaryEntries().iterator(); 448 while (it.hasNext ()) { 449 ((Entry)it.next()).copy (df.getPrimaryFile (), suffix); 450 } 451 fo = getPrimaryEntry ().copy (df.getPrimaryFile (), suffix); 453 454 boolean fullRescan = getMultiFileLoader() == null || 455 getMultiFileLoader().findPrimaryFile(fo) != fo; 456 try { 457 return fullRescan ? DataObject.find(fo) : createMultiObject (fo); 458 } catch (DataObjectExistsException ex) { 459 return ex.getDataObject (); 460 } 461 } 462 463 466 protected void handleDelete() throws IOException { 467 List<FileObject> toRemove = new ArrayList<FileObject>(); 468 Iterator<Map.Entry<FileObject,Entry>> it; 469 synchronized ( synchObjectSecondary() ) { 470 removeAllInvalid (); 471 it = new ArrayList<Map.Entry<FileObject,Entry>>(getSecondary().entrySet()).iterator(); 472 } 473 474 while (it.hasNext ()) { 475 Map.Entry<FileObject,Entry> e = it.next (); 476 e.getValue().delete(); 477 toRemove.add(e.getKey()); 478 } 479 480 synchronized ( synchObjectSecondary() ) { 481 for (FileObject f : toRemove) { 482 getSecondary().remove(f); 483 if (ERR.isLoggable(Level.FINE)) { 484 ERR.fine(" handleDelete, removed entry: " + f); 485 } 486 } 487 } 488 489 getPrimaryEntry().delete(); 490 } 491 492 494 protected FileObject handleRename (String name) throws IOException { 495 getPrimaryEntry ().changeFile (getPrimaryEntry().rename (name)); 496 497 Map<FileObject,Entry> add = null; 498 499 List<FileObject> toRemove = new ArrayList<FileObject>(); 500 501 Iterator<Map.Entry<FileObject,Entry>> it; 502 synchronized ( synchObjectSecondary() ) { 503 removeAllInvalid (); 504 it = new ArrayList<Map.Entry<FileObject,Entry>>(getSecondary().entrySet ()).iterator(); 505 } 506 507 while (it.hasNext ()) { 508 Map.Entry<FileObject,Entry> e = it.next(); 509 FileObject fo = e.getValue().rename(name); 510 if (fo == null) { 511 toRemove.add (e.getKey()); 513 } else { 514 if (!fo.equals (e.getKey ())) { 515 if (add == null) add = new HashMap<FileObject,Entry>(); 517 Entry entry = e.getValue(); 518 entry.changeFile (fo); 519 add.put (entry.getFile (), entry); 522 523 toRemove.add(e.getKey()); 525 } 526 } 527 } 528 529 if ((add != null) || (!toRemove.isEmpty())) { 531 synchronized ( synchObjectSecondary() ) { 532 if (!toRemove.isEmpty()) { 534 for (FileObject f : toRemove) { 535 getSecondary().remove(f); 536 if (ERR.isLoggable(Level.FINE)) { 537 ERR.fine("handleRename, removed: " + f + " for " + this); } 539 } 540 } 541 if (add != null) { 543 getSecondary().putAll (add); 544 if (ERR.isLoggable(Level.FINE)) { 545 ERR.fine("handleRename, putAll: " + add + " for " + this); } 547 } 548 } 549 firePropertyChangeLater (PROP_FILES, null, null); 550 } 551 552 return getPrimaryEntry ().getFile (); 553 } 554 555 562 protected FileObject handleMove (DataFolder df) throws IOException { 563 String suffix = existInFolder(getPrimaryEntry().getFile(), df.getPrimaryFile ()); 564 if (suffix == null) 565 throw new org.openide.util.UserCancelException(); 566 567 List<Pair> backup = saveEntries(); 568 569 try { 570 HashMap<FileObject,Entry> add = null; 571 572 ArrayList<FileObject> toRemove = new ArrayList<FileObject>(); 573 Iterator<Map.Entry<FileObject,Entry>> it; 574 int count; 575 synchronized ( synchObjectSecondary() ) { 576 removeAllInvalid (); 577 ArrayList<Map.Entry<FileObject,Entry>> list = 578 new ArrayList<Map.Entry<FileObject,Entry>>(getSecondary().entrySet ()); 579 count = list.size(); 580 it = list.iterator(); 581 } 582 583 if (ERR.isLoggable(Level.FINE)) { 584 ERR.fine("move " + this + " to " + df + " number of secondary entries: " + count); ERR.fine("moving primary entry: " + getPrimaryEntry()); } 587 getPrimaryEntry ().changeFile (getPrimaryEntry ().move (df.getPrimaryFile (), suffix)); 588 if (ERR.isLoggable(Level.FINE)) ERR.fine(" moved: " + getPrimaryEntry().getFile()); 590 591 while (it.hasNext ()) { 592 Map.Entry<FileObject,Entry> e = it.next (); 593 if (ERR.isLoggable(Level.FINE)) ERR.fine("moving entry :" + e); FileObject fo = (e.getValue ()).move (df.getPrimaryFile (), suffix); 595 if (ERR.isLoggable(Level.FINE)) ERR.fine(" moved to :" + fo); if (fo == null) { 597 toRemove.add(e.getKey()); 599 } else { 600 if (!fo.equals (e.getKey ())) { 601 if (add == null) add = new HashMap<FileObject,Entry> (); 603 Entry entry = e.getValue (); 604 entry.changeFile (fo); 605 add.put (entry.getFile (), entry); 608 609 toRemove.add(e.getKey()); 611 } 612 } 613 } 614 615 if ((add != null) || (!toRemove.isEmpty())) { 617 synchronized ( synchObjectSecondary() ) { 618 if (!toRemove.isEmpty()) { 620 Object [] objects = toRemove.toArray(); 621 for (int i = 0; i < objects.length; i++) { 622 getSecondary().remove(objects[i]); 623 if (ERR.isLoggable(Level.FINE)) { 624 ERR.fine("handleMove, remove: " + objects[i] + " for " + this); } 626 } 627 } 628 if (add != null) { 630 getSecondary().putAll (add); 631 if (ERR.isLoggable(Level.FINE)) { 632 ERR.fine("handleMove, putAll: " + add + " for " + this); } 634 } 635 } 636 firePropertyChangeLater (PROP_FILES, null, null); 637 } 638 639 if (ERR.isLoggable(Level.FINE)) { 640 ERR.fine("successfully moved " + this); } 642 return getPrimaryEntry ().getFile (); 643 } catch (IOException e) { 644 if (ERR.isLoggable(Level.FINE)) { 645 ERR.fine("exception is here, restoring entries " + this); ERR.log(Level.FINE, null, e); 647 } 648 restoreEntries(backup); 649 if (ERR.isLoggable(Level.FINE)) { 650 ERR.fine("entries restored " + this); } 652 throw e; 653 } 654 } 655 656 659 protected DataObject handleCreateFromTemplate ( 660 DataFolder df, String name 661 ) throws IOException { 662 if (name == null) { 663 name = FileUtil.findFreeFileName( 664 df.getPrimaryFile (), getPrimaryFile ().getName (), getPrimaryFile ().getExt () 665 ); 666 } 667 668 FileObject fo = null; 669 Map<String ,Object > params = null; 670 for (CreateFromTemplateHandler h : Lookup.getDefault().lookupAll(CreateFromTemplateHandler.class)) { 671 FileObject current = getPrimaryEntry().getFile(); 672 if (h.accept(current)) { 673 if (params == null) { 674 params = DataObject.CreateAction.findParameters(name); 675 } 676 fo = h.createFromTemplate(current, df.getPrimaryFile(), name, params); 677 assert fo != null; 678 break; 679 } 680 } 681 if (params == null) { 682 fo = getPrimaryEntry().createFromTemplate (df.getPrimaryFile (), name); 684 } 685 686 687 Iterator it = secondaryEntries().iterator(); 688 NEXT_ENTRY: while (it.hasNext ()) { 689 for (CreateFromTemplateHandler h : Lookup.getDefault().lookupAll(CreateFromTemplateHandler.class)) { 690 FileObject current = getPrimaryEntry().getFile(); 691 if (h.accept(current)) { 692 if (params == null) { 693 params = DataObject.CreateAction.findParameters(name); 694 } 695 fo = h.createFromTemplate(current, df.getPrimaryFile(), name, params); 696 assert fo != null; 697 continue NEXT_ENTRY; 698 } 699 } 700 ((Entry)it.next()).createFromTemplate (df.getPrimaryFile (), name); 701 } 702 703 try { 704 if (this instanceof DefaultDataObject) { 706 return DataObject.find(fo); 707 } 708 709 return createMultiObject (fo); 710 } catch (DataObjectExistsException ex) { 711 return ex.getDataObject (); 712 } 713 } 714 715 723 @Deprecated 724 protected final void setCookieSet (CookieSet s) { 725 setCookieSet(s, true); 726 } 727 728 734 private void setCookieSet (CookieSet s, boolean fireChange) { 735 synchronized (cookieSetLock) { 736 ChangeListener ch = getChangeListener(); 737 738 if (cookieSet != null) { 739 cookieSet.removeChangeListener (ch); 740 } 741 742 s.addChangeListener (ch); 743 cookieSet = s; 744 } 745 746 if (fireChange) { 747 fireCookieChange (); 748 } 749 } 750 751 759 protected final CookieSet getCookieSet () { 760 CookieSet s = cookieSet; 761 if (s != null) return s; 762 synchronized (cookieSetLock) { 763 if (cookieSet != null) return cookieSet; 764 765 CookieSet g = CookieSet.createGeneric(getChangeListener()); 768 g.assign(DataObject.class, this); 769 setCookieSet (g, false); 770 return cookieSet; 771 } 772 } 773 774 780 @Override 781 public <T extends Node.Cookie> T getCookie(Class <T> type) { 782 CookieSet c = cookieSet; 783 if (c != null) { 784 T cookie = c.getCookie (type); 785 if (cookie != null) return cookie; 786 } 787 return super.getCookie (type); 788 } 789 790 792 final void fireCookieChange () { 793 firePropertyChange (PROP_COOKIE, null, null); 794 } 795 796 798 private void firePropertyChangeLater ( 799 final String name, final Object oldV, final Object newV 800 ) { 801 firingProcessor.post(new Runnable () { 802 public void run () { 803 firePropertyChange (name, oldV, newV); 804 if (PROP_FILES.equals(name) || PROP_PRIMARY_FILE.equals(name)) { 805 updateFilesInCookieSet(); 806 } 807 } 808 }); 809 } 810 811 820 private void firePropFilesAfterFinishing() { 821 synchronized (delayedPropFilesLock) { 822 if (delayedPropFilesTask == null) { 823 delayedPropFilesTask = delayProcessor.post(new Runnable () { 824 public void run() { 825 FolderList l = getFolderList(); 826 if (l != null) { 827 l.waitProcessingFinished(); 828 } 829 firePropertyChangeLater(PROP_FILES, null, null); 830 } 831 }); 832 } else { 833 delayedPropFilesTask.schedule(0); 834 } 835 } 836 } 837 838 839 final void recognizedByFolder() { 840 checked = true; 841 } 842 843 private ChangeAndBefore chLis; 844 845 final ChangeAndBefore getChangeListener() { 846 if (chLis == null) { 847 chLis = new ChangeAndBefore(); 848 } 849 return chLis; 850 } 851 852 859 private final MultiDataObject.Entry createPrimaryEntry(MultiDataObject obj, FileObject fo) { 860 MultiFileLoader loader = getMultiFileLoader (); 861 862 if (loader != null) 863 return loader.createPrimaryEntry (obj, fo); 864 865 Entry e; 866 if (fo.isFolder ()) 867 e = new FileEntry.Folder(obj, fo); 868 else 869 e = new FileEntry (obj, fo); 870 871 return e; 872 } 873 874 private final MultiDataObject.Entry createSecondaryEntry(MultiDataObject obj, FileObject fo) { 875 MultiFileLoader loader = getMultiFileLoader (); 876 877 if (loader != null) 878 return loader.createSecondaryEntryImpl (obj, fo); 879 880 Entry e; 881 if (fo.isFolder ()) 882 e = new FileEntry.Folder(obj, fo); 883 else 884 e = new FileEntry (obj, fo); 885 886 return e; 887 } 888 889 private final MultiDataObject createMultiObject(FileObject fo) throws DataObjectExistsException, IOException { 890 MultiFileLoader loader = getMultiFileLoader (); 891 892 MultiDataObject obj; 893 894 if (loader != null) { 895 obj = DataObjectPool.createMultiObject(loader, fo); 896 } else { 897 obj = (MultiDataObject)getLoader ().findDataObject (fo, RECOGNIZER); 898 } 899 return obj; 900 } 901 902 private final void checkConsistency (MultiDataObject obj) { 903 MultiFileLoader loader = getMultiFileLoader (); 904 905 if (loader != null) 906 loader.checkConsistency (obj); 907 } 908 909 private final void checkFiles (MultiDataObject obj) { 910 MultiFileLoader loader = getMultiFileLoader (); 911 912 if (loader != null) 913 loader.checkFiles (obj); 914 } 915 916 private static EmptyRecognizer RECOGNIZER = new EmptyRecognizer(); 917 918 private static class EmptyRecognizer implements DataLoader.RecognizedFiles { 919 EmptyRecognizer() {} 920 public void markRecognized (FileObject fo) { 921 } 922 } 923 924 926 929 final List<Pair> saveEntries() { 930 synchronized ( synchObjectSecondary() ) { 931 LinkedList<Pair> ll = new LinkedList<Pair>(); 932 933 ll.add (new Pair(getPrimaryEntry ())); 934 for (MultiDataObject.Entry en: secondaryEntries()) { 935 ll.add (new Pair(en)); 936 } 937 return ll; 938 } 939 } 940 941 946 final void restoreEntries(List<Pair> backup) { 947 for (Pair p: backup) { 948 if (p.entry.getFile ().equals (p.file)) 949 continue; 950 if (p.file.isValid()) { 951 p.entry.changeFile (p.file); 952 } else { 953 try { 955 if (p.entry.getFile ().isData ()) 956 p.entry.changeFile (p.entry.getFile ().copy (p.file.getParent (), p.file.getName (), p.file.getExt ())); 957 else { 958 FileObject fo = p.file.getParent ().createFolder (p.file.getName ()); 959 FileUtil.copyAttributes (p.entry.getFile (), fo); 960 p.entry.changeFile (fo); 961 } 962 } catch (IOException e) { 963 } 965 } 966 } 967 } 968 969 final static class Pair { 970 MultiDataObject.Entry entry; 971 FileObject file; 972 973 Pair(MultiDataObject.Entry e) { 974 entry = e; 975 file = e.getFile (); 976 } 977 } 978 979 980 public abstract class Entry implements java.io.Serializable { 981 982 static final long serialVersionUID = 6024795908818133571L; 983 984 987 private FileObject file; 988 989 992 private transient WeakReference <FileLock> lock; 993 994 protected Entry (FileObject file) { 995 this.file = file; 996 if (!isImportant()) { 997 file.setImportant(false); 998 } 999 } 1000 1001 1004 final void changeFile (FileObject newFile) { 1005 if (newFile.equals (file)) { 1006 return; 1007 } 1008 if (ERR.isLoggable(Level.FINE)) { 1009 ERR.fine("changeFile: " + newFile + " for " + this + " of " + getDataObject()); } 1011 newFile.setImportant (isImportant ()); 1012 this.file = newFile; 1013 1014 FileLock l = lock == null ? null : (FileLock)lock.get (); 1016 if (l != null && l.isValid ()) { 1017 if (ERR.isLoggable(Level.FINE)) { 1018 ERR.fine("releasing old lock: " + this + " was: " + l); 1019 } 1020 l.releaseLock (); 1021 } 1022 lock = null; 1023 } 1024 1025 1027 public final FileObject getFile () { 1028 return file; 1029 } 1030 1031 1034 public final MultiDataObject getDataObject () { 1035 return MultiDataObject.this; 1036 } 1037 1038 1044 public boolean isImportant () { 1045 return true; 1046 } 1047 1048 1056 public abstract FileObject copy (FileObject f, String suffix) throws IOException; 1057 1058 1065 public abstract FileObject rename (String name) throws IOException; 1066 1067 1075 public abstract FileObject move (FileObject f, String suffix) throws IOException; 1076 1077 1080 public abstract void delete () throws IOException; 1081 1082 1090 public abstract FileObject createFromTemplate (FileObject f, String name) throws IOException; 1091 1092 1096 public FileLock takeLock() throws IOException { 1097 FileLock l = lock == null ? null : lock.get (); 1098 if (l == null || !l.isValid ()){ 1099 l = getFile ().lock (); 1100 lock = new WeakReference <FileLock> (l); 1101 } 1102 if (ERR.isLoggable(Level.FINE)) { 1103 ERR.fine("takeLock: " + this + " is: " + l); 1104 } 1105 return l; 1106 } 1107 1108 1111 public boolean isLocked() { 1112 FileLock l = lock == null ? null : lock.get (); 1113 return l != null && l.isValid (); 1114 } 1115 1116 public boolean equals(Object o) { 1117 if (! (o instanceof Entry)) return false; 1118 return getFile ().equals(((Entry) o).getFile ()); 1119 } 1120 1121 public int hashCode() { 1122 return getFile ().hashCode(); 1123 } 1124 1125 1132 protected Object writeReplace () { 1133 return new EntryReplace (getFile ()); 1134 } 1135 } 1136 1137 void notifyFileDeleted (FileEvent fe) { 1138 removeFile (fe.getFile ()); 1139 if (fe.getFile ().equals (getPrimaryFile ())) { 1140 try { 1141 MultiDataObject.this.markInvalid0 (); 1142 } catch (PropertyVetoException ex) { 1143 Logger.getLogger(MultiDataObject.class.getName()).log(Level.WARNING, null, ex); 1145 } 1146 } 1147 } 1148 1149 1152 void notifyFileDataCreated(FileEvent fe) { 1153 checked = false; 1154 } 1155 1156 final void updateFilesInCookieSet() { 1157 getCookieSet().assign(FileObject.class, files().toArray(new FileObject[0])); 1158 } 1159 1160 1162 private final class ChangeAndBefore implements ChangeListener, CookieSet.Before { 1163 public void stateChanged (ChangeEvent ev) { 1164 fireCookieChange (); 1165 } 1166 1167 public void beforeLookup(Class <?> clazz) { 1168 if (clazz.isAssignableFrom(FileObject.class)) { 1169 updateFilesInCookieSet(); 1170 } 1171 } 1172 } 1173 1174 1176 private static final class EntryReplace extends Object implements java.io.Serializable { 1177 1178 static final long serialVersionUID = -1498798537289529182L; 1179 1180 1181 private FileObject file; 1182 1183 private transient Entry entry; 1184 1185 public EntryReplace (FileObject fo) { 1186 file = fo; 1187 } 1188 1189 private void readObject (ObjectInputStream ois) throws IOException, ClassNotFoundException { 1190 ois.defaultReadObject (); 1191 try { 1192 DataObject obj = DataObject.find (file); 1193 if (obj instanceof MultiDataObject) { 1194 MultiDataObject m = (MultiDataObject)obj; 1195 1196 if (file.equals (m.getPrimaryFile ())) { 1197 entry = m.getPrimaryEntry (); 1199 } else { 1200 Entry e = (Entry)m.findSecondaryEntry (file); 1202 if (e == null) { 1203 throw new InvalidObjectException (obj.toString ()); 1204 } 1205 entry = e; 1207 } 1208 } 1209 } catch (DataObjectNotFoundException ex) { 1210 throw new InvalidObjectException (ex.getMessage ()); 1211 } 1212 } 1213 1214 public Object readResolve () { 1215 return entry; 1216 } 1217 } 1218} 1219 | Popular Tags |