1 19 20 package org.openide.loaders; 21 22 23 import java.awt.Image ; 24 import java.awt.datatransfer.Transferable ; 25 import java.beans.*; 26 import java.io.*; 27 import java.lang.ref.*; 28 import java.lang.reflect.InvocationTargetException ; 29 import java.net.*; 30 import java.text.MessageFormat ; 31 import java.util.*; 32 import java.util.logging.Level ; 33 import java.util.logging.Logger ; 34 import org.openide.filesystems.*; 35 import org.openide.nodes.*; 36 import org.openide.nodes.Node.*; 37 import org.openide.util.*; 38 import org.openide.util.datatransfer.ExTransferable; 39 import org.openide.xml.XMLUtil; 40 41 45 public class DataShadow extends MultiDataObject implements DataObject.Container { 46 47 static final long serialVersionUID = 6305590675982925167L; 48 49 50 private DataObject original; 51 52 private OrigL origL = null; 53 54 private LinkedList<ShadowNode> nodes = new LinkedList<ShadowNode> (); 55 56 57 static final String SHADOW_EXTENSION = "shadow"; 59 61 private static Map<FileObject, Set<Reference<DataShadow>>> allDataShadows; 62 63 private static Mutex MUTEX = new Mutex (); 64 65 66 private static synchronized Map<FileObject, Set<Reference<DataShadow>>> getDataShadowsSet() { 67 if (allDataShadows == null) { 68 allDataShadows = new HashMap<FileObject, Set<Reference<DataShadow>>>(); 69 } 70 return allDataShadows; 71 } 72 73 private static synchronized void enqueueDataShadow(DataShadow ds) { 74 Map<FileObject, Set<Reference<DataShadow>>> m = getDataShadowsSet (); 75 76 FileObject prim = ds.original.getPrimaryFile (); 77 Reference<DataShadow> ref = new DSWeakReference<DataShadow>(ds); 78 Set<Reference<DataShadow>> s = m.get (prim); 79 if (s == null) { 80 s = Collections.singleton (ref); 81 getDataShadowsSet ().put (prim, s); 82 } else { 83 if (! (s instanceof HashSet)) { 84 s = new HashSet<Reference<DataShadow>> (s); 85 getDataShadowsSet ().put (prim, s); 86 } 87 s.add (ref); 88 } 89 } 90 91 92 private static synchronized List<DataShadow> getAllDataShadows() { 93 if (allDataShadows == null || allDataShadows.isEmpty()) { 94 return null; 95 } 96 97 List<DataShadow> ret = new ArrayList<DataShadow>(allDataShadows.size()); 98 Iterator<Set<Reference<DataShadow>>> it = allDataShadows.values ().iterator(); 99 while (it.hasNext()) { 100 Set<Reference<DataShadow>> ref = it.next(); 101 Iterator<Reference<DataShadow>> refs = ref.iterator (); 102 while (refs.hasNext ()) { 103 Reference<DataShadow> r = refs.next (); 104 DataShadow shadow = r.get (); 105 if (shadow != null) { 106 ret.add (shadow); 107 } 108 } 109 } 110 111 return ret; 112 } 113 114 117 static void checkValidity(EventObject ev) { 118 DataObject src = null; 119 if (ev instanceof OperationEvent) { 120 src = ((OperationEvent)ev).getObject(); 121 } 122 123 Set<Reference<DataShadow>> shadows = null; 124 synchronized (DataShadow.class) { 125 if (allDataShadows == null || allDataShadows.isEmpty ()) return; 126 127 if (src != null) { 128 shadows = allDataShadows.get (src.getPrimaryFile ()); 129 if (shadows == null) { 130 return; 133 } 134 shadows = new HashSet<Reference<DataShadow>> (shadows); 136 } 137 } 138 139 DataObject changed = null; 140 OperationEvent.Copy c; 141 if ( 142 ev instanceof OperationEvent.Rename 143 || 144 ev instanceof OperationEvent.Move 145 ) { 146 changed = ((OperationEvent)ev).getObject(); 147 } 148 149 if (shadows != null) { 150 for (Reference<DataShadow> r: shadows) { 155 DataShadow shadow = r.get (); 156 if (shadow != null) { 157 shadow.refresh (shadow.original == changed); 158 } 159 } 160 return; 161 } 162 163 List<DataShadow> all = getAllDataShadows(); 164 if (all == null) { 165 return; 166 } 167 168 169 int size = all.size(); 170 for (int i = 0; i < size; i++) { 171 DataShadow obj = all.get(i); 172 obj.refresh (obj.original == changed); 175 } 176 } 177 178 185 protected DataShadow ( 186 FileObject fo, DataObject original, MultiFileLoader loader 187 ) throws DataObjectExistsException { 188 super (fo, loader); 189 init(original); 190 } 191 192 200 @Deprecated 201 protected DataShadow ( 202 FileObject fo, DataObject original, DataLoader loader 203 ) throws DataObjectExistsException { 204 super (fo, loader); 205 init(original); 206 } 207 208 211 private void init(DataObject original) { 212 if (original == null) 213 throw new IllegalArgumentException (); 214 setOriginal (original); 215 enqueueDataShadow(this); 216 } 217 218 222 private DataShadow (FileObject fo, DataObject original) throws DataObjectExistsException { 223 this (fo, original, (MultiFileLoader)DataLoaderPool.getShadowLoader ()); 224 } 225 226 232 public static DataShadow create (DataFolder folder, DataObject original) 233 throws IOException { 234 return create (folder, null, original, SHADOW_EXTENSION); 235 } 236 237 244 public static DataShadow create ( 245 DataFolder folder, 246 final String name, 247 final DataObject original 248 ) throws IOException { 249 return create (folder, name, original, SHADOW_EXTENSION); 250 } 251 252 259 public static DataShadow create ( 260 DataFolder folder, 261 final String name, 262 final DataObject original, 263 final String ext 264 ) throws IOException { 265 final FileObject fo = folder.getPrimaryFile (); 266 final DataShadow[] arr = new DataShadow[1]; 267 268 DataObjectPool.getPOOL().runAtomicAction(fo, new FileSystem.AtomicAction() { 269 public void run() throws IOException { 270 FileObject file = writeOriginal(name, ext, fo, original); 271 final DataObject obj = DataObject.find(file); 272 if (obj instanceof DataShadow) { 273 arr[0] = (DataShadow)obj; 274 } else { 275 throw new DataObjectNotFoundException(obj.getPrimaryFile()) { 277 public String getMessage() { 278 return super.getMessage() + ": " + obj.getClass().getName(); } 280 }; 281 } 282 } 283 }); 284 285 return arr[0]; 286 } 287 288 299 private static FileObject writeOriginal ( 300 final String name, final String ext, final FileObject trg, final DataObject obj 301 ) throws IOException { 302 try { 303 return MUTEX.writeAccess (new Mutex.ExceptionAction<FileObject> () { 304 public FileObject run () throws IOException { 305 FileObject fo; 306 if (trg.isData ()) { 307 fo = trg; 308 } else { 309 String n; 310 if (name == null) { 311 String baseName = obj.getName().replace(':', '_').replace('/', '_'); n = FileUtil.findFreeFileName (trg, baseName, ext); 314 } else { 315 n = name; 316 } 317 fo = trg.createData (n, ext); 318 } 319 writeShadowFile(fo, obj.getPrimaryFile().getURL()); 320 return fo; 321 } 322 }); 323 } catch (MutexException e) { 324 throw (IOException) e.getException (); 325 } 326 } 327 328 331 static void writeOriginal (final FileObject shadow, final URL url) throws IOException { 332 try { 333 MUTEX.writeAccess (new Mutex.ExceptionAction<Void > () { 334 public Void run () throws IOException { 335 writeShadowFile(shadow, url); 336 return null; 337 } 338 }); 339 } catch (MutexException e) { 340 throw (IOException) e.getException (); 341 } 342 } 343 344 349 private static void writeShadowFile(FileObject fo, URL url) throws IOException { 350 FileLock lock = fo.lock(); 351 Writer os = new OutputStreamWriter(fo.getOutputStream(lock), "UTF-8"); 352 try { 353 os.write(url.toExternalForm()); } finally { 355 os.close(); 356 lock.releaseLock(); 357 } 358 } 359 360 367 protected static DataObject deserialize(FileObject fileObject) throws IOException { 368 String [] fileAndFileSystem = readOriginalFileAndFileSystem(fileObject); 369 assert fileAndFileSystem[0] != null; 370 FileObject target; 371 URI u; 372 try { 373 u = new URI(fileAndFileSystem[0]); 374 } catch (URISyntaxException e) { 375 u = null; 376 } 377 if (u != null && u.isAbsolute()) { 378 target = URLMapper.findFileObject(u.toURL()); 379 } else { 380 FileSystem fs; 381 if ("SystemFileSystem".equals(fileAndFileSystem[1])) { fs = Repository.getDefault().getDefaultFileSystem(); 383 } else { 384 fs = fileObject.getFileSystem(); 386 } 387 target = fs.findResource(fileAndFileSystem[0]); 388 } 389 if (target != null) { 390 return DataObject.find(target); 391 } else { 392 throw new FileNotFoundException(fileAndFileSystem[0] + ':' + fileAndFileSystem[1]); 393 } 394 } 395 static URL readURL(FileObject fileObject) throws IOException { 396 String [] fileAndFileSystem = readOriginalFileAndFileSystem(fileObject); 397 assert fileAndFileSystem[0] != null; 398 URI u; 399 try { 400 u = new URI(fileAndFileSystem[0]); 401 } catch (URISyntaxException e) { 402 u = null; 403 } 404 if (u != null && u.isAbsolute()) { 405 return u.toURL(); 406 } else { 407 FileSystem fs; 408 if ("SystemFileSystem".equals(fileAndFileSystem[1])) { fs = Repository.getDefault().getDefaultFileSystem(); 410 } else { 411 fs = fileObject.getFileSystem(); 412 } 413 return new URL(fs.getRoot().getURL(), fileAndFileSystem[0]); 414 } 415 } 416 private static String [] readOriginalFileAndFileSystem(final FileObject f) throws IOException { 417 if ( f.getSize() == 0 ) { 418 Object fileName = f.getAttribute("originalFile"); if ( fileName instanceof String ) { 420 return new String [] {(String ) fileName, (String ) f.getAttribute("originalFileSystem")}; } else if (fileName instanceof URL) { 422 return new String [] {((URL) fileName).toExternalForm(), null}; 423 } else { 424 throw new FileNotFoundException(f.getPath()); 425 } 426 } else { 427 try { 428 return MUTEX.readAccess(new Mutex.ExceptionAction<String []>() { 429 public String [] run() throws IOException { 430 BufferedReader ois = new BufferedReader(new InputStreamReader(f.getInputStream(), "UTF-8")); try { 432 String s = ois.readLine(); 433 String fs = ois.readLine(); 434 return new String [] {s, fs}; 435 } finally { 436 ois.close(); 437 } 438 } 439 }); 440 } catch (MutexException e) { 441 throw (IOException) e.getException(); 442 } 443 } 444 } 445 446 private FileObject checkOriginal (DataObject orig) throws IOException { 447 if (orig == null) 448 return null; 449 return deserialize(getPrimaryFile()).getPrimaryFile(); 450 } 451 452 455 public DataObject getOriginal () { 456 waitUpdatesProcessed(); 457 return original; 458 } 459 460 463 public DataObject[] getChildren () { 464 return new DataObject[] { original }; 465 } 466 467 469 protected Node createNodeDelegate () { 470 return new ShadowNode (this); 471 } 472 473 476 public boolean isDeleteAllowed () { 477 return getPrimaryFile().canWrite(); 478 } 479 480 483 public boolean isCopyAllowed () { 484 return true; 485 } 486 487 490 public boolean isMoveAllowed () { 491 return getPrimaryFile().canWrite(); 492 } 493 494 497 public boolean isRenameAllowed () { 498 return getPrimaryFile().canWrite(); 499 } 500 501 504 public HelpCtx getHelpCtx () { 505 return original.getHelpCtx (); 506 } 507 508 515 protected DataShadow handleCreateShadow (DataFolder f) throws IOException { 516 if (original instanceof DataFolder) { 517 DataFolder.testNesting(((DataFolder)original), f); 518 } 519 return original.handleCreateShadow (f); 520 } 521 522 523 @Override 524 public <T extends Node.Cookie> T getCookie(Class <T> c) { 525 if (c.isInstance(this)) { 526 return c.cast(this); 527 } 528 return original.getCookie (this, c); 529 } 530 531 532 public void refresh() { 533 refresh(false); 534 } 535 536 private void refresh(boolean moved) { 537 try { 538 539 if (moved) 540 tryUpdate(); 541 FileObject obj = checkOriginal(original); 542 if (obj != null) { 543 if (obj != this.original.getPrimaryFile ()) { 544 this.setOriginal (DataObject.find (obj)); 545 } 546 return; 547 } 548 } catch (IOException e) { 549 } 550 try { 551 552 this.setValid(false); 553 } catch (java.beans.PropertyVetoException e) { 554 } 555 } 556 557 private void tryUpdate() throws IOException { 558 URL url = readURL(getPrimaryFile ()); 559 if (url.equals(original.getPrimaryFile().getURL())) { 560 return; 561 } 562 writeOriginal (null, null, getPrimaryFile (), original); 563 } 564 565 private void setOriginal (DataObject o) { 566 if (origL == null) { 567 origL = new OrigL (this); 568 } 569 570 if (original != null) { 572 original.removePropertyChangeListener (origL); 573 } 574 575 DataObject oldOriginal = original; 576 577 o.addPropertyChangeListener (origL); 578 original = o; 579 580 ShadowNode n [] = null; 582 synchronized (nodes) { 583 n = (ShadowNode [])nodes.toArray (new ShadowNode [nodes.size ()]); 584 } 585 586 try { 587 for (int i = 0; i < n.length; i++) { 588 n[i].originalChanged (); 589 } 590 } 591 catch (IllegalStateException e) { 592 System.out.println("Please reopen the bug #18998 if you see this message."); System.out.println("Old:"+oldOriginal + ((oldOriginal == null) ? "" : (" / " + oldOriginal.isValid() + " / " + System.identityHashCode(oldOriginal)))); System.out.println("New:"+original + ((original == null) ? "" : (" / " + original.isValid() + " / " + System.identityHashCode(original)))); throw e; 598 } 599 } 600 601 private static RequestProcessor RP = new RequestProcessor("DataShadow validity check"); 602 private static Reference<Task> lastTask = new WeakReference<Task>(null); 603 604 private static void updateShadowOriginal(DataShadow shadow) { 605 class Updator implements Runnable { 606 DataShadow sh; 607 FileObject primary; 608 609 public void run () { 610 DataObject newOrig; 611 612 try { 613 newOrig = DataObject.find (primary); 614 } catch (DataObjectNotFoundException e) { 615 newOrig = null; 616 } 617 618 if (newOrig != null) { 619 sh.setOriginal (newOrig); 620 } else { 621 checkValidity (new OperationEvent (sh.original)); 622 } 623 624 primary = null; 625 sh = null; 626 } 627 } 628 Updator u = new Updator(); 629 u.sh = shadow; 630 u.primary = u.sh.original.getPrimaryFile (); 631 ERR.fine("updateShadowOriginal: " + u.sh + " primary " + u.primary); lastTask = new WeakReference<Task>(RP.post(u, 100, Thread.MIN_PRIORITY + 1)); 633 } 634 635 637 static final void waitUpdatesProcessed() { 638 if (!RP.isRequestProcessorThread()) { 639 Task t = lastTask.get(); 640 if (t != null) { 641 t.waitFinished(); 642 } 643 } 644 } 645 646 protected DataObject handleCopy (DataFolder f) throws IOException { 647 if (original instanceof DataFolder) { 648 DataFolder.testNesting(((DataFolder)original), f); 649 } 650 return super.handleCopy(f); 651 } 652 653 protected FileObject handleMove (DataFolder f) throws IOException { 654 if (original instanceof DataFolder) { 655 DataFolder.testNesting(((DataFolder)original), f); 656 } 657 return super.handleMove(f); 658 } 659 660 private static class OrigL implements PropertyChangeListener { 661 Reference<DataShadow> shadow = null; 662 public OrigL (DataShadow shadow) { 663 this.shadow = new WeakReference<DataShadow> (shadow); 664 } 665 public void propertyChange (PropertyChangeEvent evt) { 666 final DataShadow shadow = this.shadow.get (); 667 668 if (shadow != null && DataObject.PROP_VALID.equals (evt.getPropertyName ())) { 669 updateShadowOriginal(shadow); 670 } 671 } 672 } 673 674 675 protected static class ShadowNode extends FilterNode { 676 677 private static MessageFormat format; 678 679 private static MessageFormat descriptionFormat; 680 683 private static final String ATTR_USEOWNNAME = "UseOwnName"; 685 686 private DataShadow obj; 687 688 689 private Sheet sheet; 690 691 694 public ShadowNode (DataShadow shadow) { 695 this (shadow, shadow.original.getNodeDelegate ()); 696 } 697 698 699 private ShadowNode (DataShadow shadow, Node node) { 700 super (node); 701 this.obj = shadow; 702 synchronized (this.obj.nodes) { 703 this.obj.nodes.add (this); 704 } 705 } 706 707 709 public Node cloneNode () { 710 ShadowNode sn = new ShadowNode (obj); 711 return sn; 712 } 713 714 718 public void setName (String name) { 719 try { 720 if (!name.equals (obj.getName ())) { 721 obj.rename (name); 722 if (obj.original.getPrimaryFile ().isRoot ()) { 723 obj.getPrimaryFile ().setAttribute (ATTR_USEOWNNAME, Boolean.TRUE); 724 } 725 fireDisplayNameChange (null, null); 726 fireNameChange (null, null); 727 } 728 } catch (IOException ex) { 729 throw new IllegalArgumentException (ex.getMessage ()); 730 } 731 } 732 733 736 public String getName () { 737 return obj.getName (); 738 } 739 740 742 public String getDisplayName () { 743 if (format == null) { 744 format = new MessageFormat (NbBundle.getBundle (DataShadow.class).getString ("FMT_shadowName")); 745 } 746 String n = format.format (createArguments ()); 747 try { 748 return obj.getPrimaryFile().getFileSystem().getStatus().annotateName(n, obj.files()); 749 } catch (FileStateInvalidException fsie) { 750 return n; 752 } 753 } 754 public String getHtmlDisplayName() { 755 if (format == null) { 756 format = new MessageFormat (NbBundle.getBundle(DataShadow.class).getString("FMT_shadowName")); 757 } 758 try { 759 String n = XMLUtil.toElementContent(format.format(createArguments())); 760 FileSystem.Status s = obj.getPrimaryFile().getFileSystem().getStatus(); 761 if (s instanceof FileSystem.HtmlStatus) { 762 return ((FileSystem.HtmlStatus) s).annotateNameHtml(n, obj.files()); 763 } 764 } catch (IOException e) { 765 } 767 return null; 768 } 769 770 771 private Object [] createArguments () { 772 String origDisp; 773 String shadowName = obj.getName (); 774 if (obj.original.isValid()) { 775 origDisp = obj.original.getNodeDelegate().getDisplayName(); 776 } else { 777 origDisp = ""; } 780 Boolean useOwnName = (Boolean )obj.getPrimaryFile ().getAttribute (ATTR_USEOWNNAME); 781 if (obj.original.getPrimaryFile ().isRoot () && 782 (useOwnName == null || !useOwnName.booleanValue ())) { 783 try { 784 shadowName = obj.original.getPrimaryFile ().getFileSystem ().getDisplayName (); 785 } catch (FileStateInvalidException e) { 786 } 788 } 789 return new Object [] { 790 shadowName, super.getDisplayName (), systemNameOrFileName (obj.getPrimaryFile ()), systemNameOrFileName (obj.original.getPrimaryFile ()), origDisp, }; 796 } 797 798 800 private static String systemNameOrFileName (FileObject fo) { 801 return FileUtil.getFileDisplayName(fo); 802 } 803 804 806 public String getShortDescription () { 807 if (descriptionFormat == null) { 808 descriptionFormat = new MessageFormat ( 809 NbBundle.getBundle (DataShadow.class).getString ("FMT_shadowHint") 810 ); 811 } 812 return descriptionFormat.format (createArguments ()); 813 } 814 815 817 public Image getIcon(int type) { 818 Image i = rootIcon(type); 819 if (i != null) { 820 return i; 821 } else { 822 return super.getIcon(type); 823 } 824 } 825 public Image getOpenedIcon(int type) { 826 Image i = rootIcon(type); 827 if (i != null) { 828 return i; 829 } else { 830 return super.getOpenedIcon(type); 831 } 832 } 833 private Image rootIcon(int type) { 834 FileObject orig = obj.original.getPrimaryFile(); 835 if (orig.isRoot()) { 836 try { 837 FileSystem fs = orig.getFileSystem(); 838 try { 839 Image i = Introspector.getBeanInfo(fs.getClass()).getIcon(type); 840 return fs.getStatus().annotateIcon(i, type, obj.original.files()); 841 } catch (IntrospectionException ie) { 842 Logger.getLogger(DataShadow.class.getName()).log(Level.WARNING, null, ie); 843 } 845 } catch (FileStateInvalidException fsie) { 846 } 848 } 849 return null; 850 } 851 852 853 public boolean canDestroy () { 854 return obj.isDeleteAllowed (); 855 } 856 857 859 public void destroy () throws IOException { 860 synchronized (obj.nodes) { 861 obj.nodes.remove (this); 862 } 863 obj.delete (); 864 } 866 867 869 public final boolean canRename () { 870 return obj.isRenameAllowed (); 871 } 872 873 876 public final boolean canCopy () { 877 return obj.isCopyAllowed (); 878 } 879 880 883 public final boolean canCut () { 884 return obj.isMoveAllowed (); 885 } 886 887 894 @Override 895 public <T extends Node.Cookie> T getCookie(Class <T> cl) { 896 T c = obj.getCookie(cl); 897 if (c != null) { 898 return c; 899 } else { 900 return super.getCookie (cl); 901 } 902 } 903 904 907 public PropertySet[] getPropertySets () { 908 Sheet s = sheet; 909 if (s == null) { 910 s = sheet = cloneSheet (); 911 } 912 return s.toArray (); 913 } 914 915 921 public Transferable clipboardCopy () throws IOException { 922 ExTransferable t = ExTransferable.create (super.clipboardCopy ()); 923 t.put (LoaderTransfer.transferable ( 924 obj, 925 LoaderTransfer.CLIPBOARD_COPY) 926 ); 927 return t; 928 } 929 930 936 public Transferable clipboardCut () throws IOException { 937 ExTransferable t = ExTransferable.create (super.clipboardCut ()); 938 t.put (LoaderTransfer.transferable ( 939 obj, 940 LoaderTransfer.CLIPBOARD_CUT) 941 ); 942 return t; 943 } 944 952 public Transferable drag () throws IOException { 953 return clipboardCopy (); 954 } 955 956 962 protected org.openide.nodes.NodeListener createNodeListener () { 963 return new PropL (this); 964 } 965 966 968 public boolean equals (Object o) { 969 if (o instanceof ShadowNode) { 970 ShadowNode sn = (ShadowNode)o; 971 return sn.obj == obj; 972 } 973 return false; 974 } 975 976 978 public int hashCode () { 979 return obj.hashCode (); 980 } 981 982 983 985 private Sheet cloneSheet () { 986 PropertySet[] sets = this.getOriginal().getPropertySets (); 987 988 Sheet s = new Sheet (); 989 for (int i = 0; i < sets.length; i++) { 990 Sheet.Set ss = new Sheet.Set (); 991 ss.put (sets[i].getProperties ()); 992 ss.setName (sets[i].getName ()); 993 ss.setDisplayName (sets[i].getDisplayName ()); 994 ss.setShortDescription (sets[i].getShortDescription ()); 995 996 modifySheetSet (ss); 998 999 s.put (ss); 1000 } 1001 1002 return s; 1003 } 1004 1005 1008 private void modifySheetSet (Sheet.Set ss) { 1009 Property p = ss.remove (DataObject.PROP_NAME); 1010 if (p != null) { 1011 p = new PropertySupport.Name (this); 1012 ss.put (p); 1013 1014 p = new Name (); 1015 ss.put (p); 1016 } 1017 } 1018 1019 private void originalChanged () { 1020 DataObject ori = obj.original; 1021 if (ori.isValid()) { 1022 changeOriginal (ori.getNodeDelegate(), true); 1023 } else { 1024 updateShadowOriginal(obj); 1025 } 1026 } 1027 1028 1031 private final class Name extends PropertySupport.ReadWrite<String > { 1032 public Name () { 1033 super ( 1034 "OriginalName", String .class, 1036 DataObject.getString ("PROP_ShadowOriginalName"), 1037 DataObject.getString ("HINT_ShadowOriginalName") 1038 ); 1039 } 1040 1041 public String getValue () { 1042 return obj.original.getName(); 1043 } 1044 1045 public void setValue (String val) throws IllegalAccessException , 1046 IllegalArgumentException , InvocationTargetException { 1047 if (!canWrite()) 1048 throw new IllegalAccessException (); 1049 1050 try { 1051 DataObject orig = obj.original; 1052 orig.rename (val); 1053 writeOriginal (null, null, obj.getPrimaryFile (), orig); 1054 } catch (IOException ex) { 1055 throw new InvocationTargetException (ex); 1056 } 1057 } 1058 1059 public boolean canWrite () { 1060 return obj.original.isRenameAllowed(); 1061 } 1062 } 1063 1064 1067 private static class PropL extends FilterNode.NodeAdapter { 1068 public PropL (ShadowNode sn) { 1069 super (sn); 1070 } 1071 1072 protected void propertyChange (FilterNode fn, PropertyChangeEvent ev) { 1073 if (Node.PROP_PROPERTY_SETS.equals(ev.getPropertyName ())) { 1074 ShadowNode sn = (ShadowNode)fn; 1076 sn.sheet = null; 1077 } 1078 1079 super.propertyChange (fn, ev); 1080 } 1081 } 1082 } 1083 1084 static final class DSWeakReference<T> extends WeakReference<T> 1085 implements Runnable { 1086 private int hash; 1087 private FileObject original; 1088 1089 DSWeakReference(T o) { 1090 super(o, org.openide.util.Utilities.activeReferenceQueue()); 1091 this.hash = o.hashCode(); 1092 if (o instanceof DataShadow) { 1093 DataShadow s = (DataShadow)o; 1094 this.original = s.original.getPrimaryFile (); 1095 } 1096 } 1097 1098 public int hashCode() { 1099 return hash; 1100 } 1101 1102 public boolean equals(Object o) { 1103 T mine = get(); 1104 if (mine == null) { 1105 return false; 1106 } 1107 1108 if (o instanceof DSWeakReference) { 1109 DSWeakReference him = (DSWeakReference) o; 1110 return mine.equals(him.get()); 1111 } 1112 1113 return false; 1114 } 1115 1116 public void run() { 1117 if (original != null) { 1118 synchronized (getDataShadowsSet ()) { 1119 getDataShadowsSet().remove(original); 1120 } 1121 } else { 1122 synchronized (BrokenDataShadow.getDataShadowsSet()) { 1123 BrokenDataShadow.getDataShadowsSet().remove(this); } 1125 } 1126 } 1127 } 1128} 1129 | Popular Tags |