1 19 20 package org.openide.loaders; 21 22 import java.awt.Image ; 23 import java.awt.datatransfer.*; 24 import java.beans.*; 25 import java.io.*; 26 import java.lang.reflect.InvocationTargetException ; 27 import java.net.URI ; 28 import java.util.*; 29 import java.util.logging.Level ; 30 import java.util.logging.Logger ; 31 import javax.swing.*; 32 import javax.swing.event.ChangeEvent ; 33 import org.openide.*; 34 import org.openide.cookies.*; 35 import org.openide.filesystems.*; 36 import org.openide.nodes.*; 37 import org.openide.util.*; 38 import org.openide.util.datatransfer.*; 39 40 48 public class DataFolder extends MultiDataObject implements DataObject.Container { 49 50 static final long serialVersionUID = -8244904281845488751L; 51 52 53 public static final String PROP_CHILDREN = DataObject.Container.PROP_CHILDREN; 54 55 56 public static final String PROP_SORT_MODE = "sortMode"; 58 59 static final String EA_SORT_MODE = "OpenIDE-Folder-SortMode"; 61 static final String EA_ORDER = "OpenIDE-Folder-Order"; 63 64 public static final String PROP_ORDER = "order"; 66 public static final String SET_SORTING = "sorting"; 68 69 private static final String FOLDER_ICON_BASE = 70 "org/openide/loaders/defaultFolder.gif"; 72 73 private static final String ROOT_SHADOW_NAME = "Root"; 75 76 private static DataFlavor uriListDataFlavor; 77 78 81 private FolderList list; 82 83 84 private PropertyChangeListener pcl; 85 86 private DataTransferSupport dataTransferSupport = new Paste (); 87 88 98 @Deprecated 99 public DataFolder (FileObject fo) 100 throws DataObjectExistsException, IllegalArgumentException { 101 this(fo, DataLoaderPool.getFolderLoader ()); 102 } 103 104 111 protected DataFolder (FileObject fo, MultiFileLoader loader) 112 throws DataObjectExistsException, IllegalArgumentException { 113 this (fo, loader, true); 114 } 115 116 123 @Deprecated 124 protected DataFolder (FileObject fo, DataLoader loader) 125 throws DataObjectExistsException, IllegalArgumentException { 126 super (fo, loader); 127 init(fo, true); 128 } 129 130 137 private DataFolder (FileObject fo, MultiFileLoader loader, boolean attach) 138 throws DataObjectExistsException, IllegalArgumentException { 139 super (fo, loader); 140 init(fo, attach); 141 } 142 143 147 private void init(FileObject fo, boolean attach) throws IllegalArgumentException { 148 if (!fo.isFolder ()) { 149 throw new IllegalArgumentException ("Not folder: " + fo); } 152 list = reassignList (fo, attach); 153 } 154 155 159 private FolderList reassignList (FileObject fo, boolean attach) { 160 FolderList list = FolderList.find (fo, true); 163 164 if (attach) { 165 pcl = new ListPCL (); 166 list.addPropertyChangeListener (org.openide.util.WeakListeners.propertyChange (pcl, list)); 167 } 168 169 return list; 170 } 171 172 173 181 public static DataFolder create (DataFolder folder, String name) throws IOException { 182 StringTokenizer tok = new StringTokenizer (name, "/"); while (tok.hasMoreTokens ()) { 184 String piece = tok.nextToken (); 185 if (! confirmName (piece)) { 186 throw new IOException (NbBundle.getMessage (DataFolder.class, "EXC_WrongName", piece)); 187 } 188 } 189 return DataFolder.findFolder (FileUtil.createFolder (folder.getPrimaryFile (), name)); 190 } 191 192 196 public synchronized final void setSortMode (SortMode mode) throws IOException { 197 SortMode old = getOrder ().getSortMode (); 198 getOrder ().setSortMode (mode); 199 firePropertyChange (PROP_SORT_MODE, old, getOrder ().getSortMode ()); 200 } 201 202 205 public final SortMode getSortMode () { 206 return getOrder ().getSortMode (); 207 } 208 209 223 public synchronized final void setOrder (DataObject[] arr) throws IOException { 224 getOrder ().setOrder (arr); 225 firePropertyChange (PROP_ORDER, null, null); 226 } 227 228 231 private FolderOrder getOrder () { 232 return FolderOrder.findFor (getPrimaryFile ()); 233 } 234 235 239 public String getName () { 240 return getPrimaryFile ().getNameExt (); 241 } 242 243 246 public DataObject[] getChildren () { 247 return list.getChildren (); 248 } 249 250 253 final List<DataObject> getChildrenList () { 254 return list.getChildrenList (); 255 } 256 257 261 final RequestProcessor.Task computeChildrenList (FolderListListener l) { 262 return list.computeChildrenList (l); 263 } 264 265 268 public Enumeration<DataObject> children () { 269 return Collections.enumeration (getChildrenList ()); 270 } 271 272 278 public Enumeration<DataObject> children (final boolean rec) { 279 if (!rec) { 280 return children(); 281 } 282 283 class Processor implements org.openide.util.Enumerations.Processor<DataObject, DataObject> { 284 285 public DataObject process (DataObject dataObj, Collection<DataObject> toAdd) { 286 if (rec && dataObj instanceof DataFolder) { 287 toAdd.addAll (Arrays.asList (((DataFolder)dataObj).getChildren())); 288 } 289 return dataObj; 290 } 291 } 292 Enumeration<DataObject> en = org.openide.util.Enumerations.queue ( 293 org.openide.util.Enumerations.array (getChildren ()), 294 new Processor () 295 ); 296 return en; 297 } 298 299 301 protected synchronized Node createNodeDelegate () { 302 return new FolderNode(); 303 } 304 305 private final class ClonedFilter extends FilterNode { 306 private DataFilter filter; 307 private int hashCode = -1; 310 public ClonedFilter (Node n, DataFilter filter) { 311 super (n, DataFolder.this.createNodeChildren (filter)); 312 this.filter = filter; 313 } 314 public ClonedFilter (DataFilter filter) { 315 this (DataFolder.this.getNodeDelegate (), filter); 316 } 317 public Node cloneNode () { 318 if (isValid()) { 319 return new ClonedFilter (filter); 320 } else { 321 return super.cloneNode(); 322 } 323 } 324 public Node.Handle getHandle () { 325 return new ClonedFilterHandle (DataFolder.this, filter); 326 } 327 public boolean equals (Object o) { 328 if (o == null) { 329 return false; 330 } else if (o == this) { 331 return true; 332 } else if (o instanceof FolderNode) { 333 FolderNode fn = (FolderNode) o; 334 if (fn.getCookie (DataFolder.class) != DataFolder.this) return false; 335 org.openide.nodes.Children ch = fn.getChildren (); 336 return (ch instanceof FolderChildren) && 337 ((FolderChildren) ch).getFilter ().equals (filter); 338 } else if (o instanceof ClonedFilter) { 339 ClonedFilter cf = (ClonedFilter) o; 340 return cf.getCookie (DataFolder.class) == DataFolder.this && 341 cf.filter.equals (filter); 342 } else { 343 return false; 344 } 345 } 346 public int hashCode () { 347 if ( hashCode == -1 ) { 348 if ( isValid() ) { 349 hashCode = getNodeDelegate().hashCode(); 350 } 351 else { 352 hashCode = super.hashCode(); 353 } 354 355 if ( hashCode == -1 ) { 356 hashCode = -2; 357 } 358 359 } 360 return hashCode; 361 362 } 363 } 364 private final static class ClonedFilterHandle implements Node.Handle { 365 private final static long serialVersionUID = 24234097765186L; 366 private DataObject folder; 367 private DataFilter filter; 368 public ClonedFilterHandle (DataFolder folder, DataFilter filter) { 369 this.folder = folder; 370 this.filter = filter; 371 } 372 public Node getNode () throws IOException { 373 if (folder instanceof DataFolder) { 374 return ((DataFolder)folder).new ClonedFilter (filter); 375 } else { 376 throw new java.io.InvalidObjectException ( 377 folder == null ? "" : folder.toString() ); 379 } 380 } 381 } 382 387 Node getClonedNodeDelegate (DataFilter filter) { 388 Node n = getNodeDelegate (); 389 Children c = n.getChildren (); 390 if (c.getClass () == FolderChildren.class) { 392 DataFilter f = ((FolderChildren) c).getFilter (); 393 if (f == DataFilter.ALL) { 394 return new ClonedFilter (n, filter); 398 } else if (filter != DataFilter.ALL && filter != f) { 399 return new ClonedFilter (n, filterCompose (f, filter)); 403 } else { 404 return n.cloneNode (); 408 } 409 } else { 410 return n.cloneNode (); 413 } 414 } 415 416 417 private static DataFilter filterCompose (final DataFilter f1, final DataFilter f2) { 418 if (f1.equals (f2)) { 419 return f1; 420 } else { 421 return new DataFilter () { 422 public boolean acceptDataObject (DataObject obj) { 423 return f1.acceptDataObject (obj) && f2.acceptDataObject (obj); 424 } 425 }; 426 } 427 } 428 429 436 public Children createNodeChildren (DataFilter filter) { 437 return new FolderChildren (this, filter); 438 } 439 440 443 public boolean isDeleteAllowed () { 444 return isRenameAllowed (); 445 } 446 447 450 public boolean isCopyAllowed () { 451 return true; 452 } 453 454 457 public boolean isMoveAllowed () { 458 return isRenameAllowed (); 459 } 460 461 464 public boolean isRenameAllowed () { 465 FileObject fo = getPrimaryFile (); 466 return !fo.isRoot() && fo.canWrite(); 467 } 468 469 472 public HelpCtx getHelpCtx () { 473 return null; 474 } 475 476 481 public static DataFolder findFolder (FileObject fo) { 482 DataObject d; 483 try { 484 d = DataObject.find(fo); 485 } catch (DataObjectNotFoundException e) { 486 throw (IllegalArgumentException )new IllegalArgumentException (e.toString()).initCause(e); 487 } 488 if (!(d instanceof DataFolder)) { 489 throw new IllegalArgumentException ("Not a DataFolder: " + fo + " (was a " + d.getClass().getName() + ") (file is folder? " + fo.isFolder() + ")"); } 491 return (DataFolder)d; 492 } 493 494 501 public static DataObject.Container findContainer (FileObject fo) { 502 if (fo.isFolder ()) { 503 return FolderList.find (fo, true); 504 } else { 505 throw new IllegalArgumentException ("Not a folder: " + fo); } 507 } 508 509 517 protected DataObject handleCopy (DataFolder f) throws IOException { 518 testNesting(this, f); 519 520 Enumeration en = children (); 521 522 DataFolder newFolder = (DataFolder)super.handleCopy (f); 523 524 while (en.hasMoreElements ()) { 525 try { 526 DataObject obj = (DataObject)en.nextElement (); 527 if (obj.isCopyAllowed()) { 528 obj.copy (newFolder); 529 } else { 530 DataObject.LOG.warning( 532 NbBundle.getMessage(DataFolder.class, 533 "FMT_CannotCopyDo", obj.getName() ) 534 ); 535 } 536 } catch (IOException ex) { 537 Exceptions.printStackTrace(ex); 538 } 539 } 540 541 return newFolder; 542 } 543 544 548 static void testNesting(DataFolder folder, DataFolder targetFolder) throws IOException { 549 if (targetFolder.equals(folder)) { 550 IOException ioe = new IOException("Error Copying File or Folder"); Exceptions.attachLocalizedMessage(ioe, NbBundle.getMessage(DataFolder.class, "EXC_CannotCopyTheSame", folder.getName())); 552 throw ioe; 553 } else { 554 DataFolder testFolder = targetFolder.getFolder(); 555 while (testFolder != null) { 556 if (testFolder.equals(folder)) { 557 IOException ioe = new IOException("Error copying file or folder: " + 558 folder.getPrimaryFile() + " cannot be copied to its subfolder " + 559 targetFolder.getPrimaryFile()); 560 Exceptions.attachLocalizedMessage(ioe, NbBundle.getMessage(DataFolder.class, "EXC_CannotCopySubfolder", folder.getName())); 561 throw ioe; 562 } 563 testFolder = testFolder.getFolder(); 564 } 565 } 566 } 567 568 571 protected void handleDelete () throws IOException { 572 Enumeration en = children (); 573 FileLock lightWeightLock = null; try { 575 lightWeightLock = createLightWeightLock(this); 576 while (en.hasMoreElements ()) { 577 DataObject obj = (DataObject)en.nextElement (); 578 if (obj.isValid ()) { 579 obj.delete (); 580 } 581 } 582 } catch (IOException iex) { 583 584 FileObject fo = getPrimaryFile(); 585 String message = NbBundle.getMessage(DataFolder.class, "EXC_CannotDelete2", FileUtil.getFileDisplayName(fo)); 586 Exceptions.attachLocalizedMessage(iex, message); 587 throw iex; 588 } finally { 589 if (lightWeightLock != null) { 590 lightWeightLock.releaseLock(); 591 } 592 } 593 594 super.handleDelete (); 595 } 596 597 private static FileLock createLightWeightLock(DataFolder df) { FileObject fo = df.getPrimaryFile(); 599 assert fo != null; 600 Object o = fo.getAttribute("LIGHTWEIGHT_LOCK_SET"); assert o == null || (o instanceof FileLock) : fo.toString(); 602 return (FileLock)o; 603 } 604 605 612 protected FileObject handleRename (final String name) throws IOException { 613 if (! confirmName (name)) { 614 IOException e = new IOException("bad name: " + name); Exceptions.attachLocalizedMessage(e, NbBundle.getMessage(DataFolder.class, "EXC_WrongName", name)); 616 throw e; 617 } 618 return super.handleRename (name); 619 } 620 621 private static final ThreadLocal <boolean[]> KEEP_ALIVE = new ThreadLocal <boolean[]>(); 622 623 629 protected FileObject handleMove (DataFolder df) throws IOException { 630 FileObject originalFolder = getPrimaryFile (); 631 FileLock lock = originalFolder.lock(); 632 List<Pair> backup = saveEntries(); 633 634 boolean clearKeepAlive = false; 635 try { 636 638 FileObject newFile = super.handleMove (df); 639 640 DataFolder newFolder = null; 641 boolean dispose = false; 642 643 boolean[] keepAlive = KEEP_ALIVE.get(); 644 if (keepAlive == null) { 645 keepAlive = new boolean[] { false }; 646 KEEP_ALIVE.set(keepAlive); 647 } 648 649 685 final int COUNT_DOWN_INIT = 20; 686 int countDown = COUNT_DOWN_INIT; 687 while (countDown >= 0) { 688 countDown--; 689 try { 690 Object loader = getMultiFileLoader (); 692 assert loader instanceof DataLoaderPool.FolderLoader : "This has to be FolderLoader: " + loader + " for " + getPrimaryFile (); DataLoaderPool.FolderLoader folderLoader = (DataLoaderPool.FolderLoader) loader; 694 newFolder = (DataFolder) DataObjectPool.createMultiObject (folderLoader, newFile, this); 695 dispose = false; 696 break; 697 } catch (DataObjectExistsException e) { 698 newFolder = (DataFolder)e.getDataObject (); 700 newFolder.dispose(); 701 dispose = true; 702 } 703 } 704 705 Enumeration en = children (); 707 708 while (en.hasMoreElements ()) { 709 try { 710 DataObject obj = (DataObject)en.nextElement (); 711 if (obj.isMoveAllowed ()) { 712 obj.move (newFolder); 713 } else { 714 keepAlive[0] = true; 715 716 DataObject.LOG.warning( 718 NbBundle.getMessage (DataFolder.class, 719 "FMT_CannotMoveDo", obj.getName ()) 720 ); 721 } 722 } catch (IOException ex) { 723 keepAlive[0] = true; 724 Exceptions.printStackTrace(ex); 725 } 726 } 727 728 if (keepAlive[0]) { 729 restoreEntries (backup); 731 list.refresh (); 732 return originalFolder; 733 } 734 735 try { 737 originalFolder.delete (lock); 738 } catch (IOException e) { 739 Throwable t = Exceptions.attachLocalizedMessage(e, 740 org.openide.loaders.DataObject.getString("EXC_folder_delete_failed")); Exceptions.printStackTrace(t); 742 } 743 744 if (dispose) { 745 try { 747 setValid (false); 748 newFile = originalFolder; 749 } catch (PropertyVetoException e) { 750 restoreEntries (backup); 752 newFile = getPrimaryEntry ().getFile (); 753 } 754 } else { 755 item.changePrimaryFile (newFile); 759 newFolder.dispose (); 760 list = reassignList (newFile, true); 761 } 762 763 return newFile; 764 } finally { 765 if (clearKeepAlive) { 766 KEEP_ALIVE.remove(); 767 } 768 lock.releaseLock(); 769 } 770 } 771 772 777 protected DataObject handleCreateFromTemplate ( 778 DataFolder f, String name 779 ) throws IOException { 780 DataFolder newFolder = (DataFolder)super.handleCreateFromTemplate (f, name); 781 Enumeration en = children (); 782 783 while (en.hasMoreElements ()) { 784 try { 785 DataObject obj = (DataObject)en.nextElement (); 786 obj.createFromTemplate (newFolder); 787 } catch (IOException ex) { 788 Exceptions.printStackTrace(ex); 789 } 790 } 791 792 return newFolder; 793 } 794 795 803 protected DataShadow handleCreateShadow (DataFolder f) throws IOException { 804 testNesting(this, f); 806 807 String name; 808 if (getPrimaryFile ().isRoot ()) { 809 name = FileUtil.findFreeFileName ( 810 f.getPrimaryFile (), ROOT_SHADOW_NAME, DataShadow.SHADOW_EXTENSION 811 ); 812 } else { 813 name = null; 814 } 815 816 return DataShadow.create (f, name, this); 817 } 818 819 823 boolean isMergingFolders(FileObject who, FileObject targetFolder) { 824 return !targetFolder.equals (who.getParent ()); 825 } 826 827 829 public static class Index extends org.openide.nodes.Index.Support { 830 831 832 private DataFolder df; 833 834 private Node node; 835 836 private Listener listener; 837 838 842 @Deprecated 843 public Index(final DataFolder df) { 844 this (df, df.getNodeDelegate ()); 845 } 846 847 851 public Index(final DataFolder df, Node node) { 852 this.df = df; 853 this.node = node; 854 listener = new Listener (); 855 node.addNodeListener (org.openide.nodes.NodeOp.weakNodeListener (listener, node)); 856 } 857 858 860 public int getNodesCount () { 861 return node.getChildren().getNodes(FolderChildren.checkChildrenMutex()).length; 862 } 863 864 867 public Node[] getNodes () { 868 return node.getChildren().getNodes(FolderChildren.checkChildrenMutex()); 869 } 870 871 876 public void reorder (int[] perm) { 877 DataObject[] curObjs = df.getChildren(); 884 DataObject[] newObjs = new DataObject[curObjs.length]; 885 Node[] nodes = getNodes (); 886 if (nodes.length != perm.length) { 887 throw new IllegalArgumentException ("permutation of incorrect length: " + perm.length + " rather than " + nodes.length); } 889 890 HashMap<String , DataObject> names = new HashMap<String , DataObject> (2 * curObjs.length); 893 for (int i = 0; i < curObjs.length; i++) { 894 Node del = curObjs[i].getNodeDelegate (); 895 if (del.getCookie (DataObject.class) == null) { 896 names.put (del.getName (), curObjs[i]); 897 } 898 } 899 900 DataObject[] dperm = new DataObject[perm.length]; 901 for (int i = 0; i < perm.length; i++) { 902 DataObject d = nodes[i].getCookie(DataObject.class); 903 904 if (d == null) { 905 d = names.get (nodes[i].getName ()); 907 } 908 909 910 if (d == null) { 911 throw new IllegalArgumentException ("cannot reorder node with no DataObject: " + nodes[i]); } 913 if (d.getFolder () != df) { 914 throw new IllegalArgumentException ("wrong folder for: " + d.getPrimaryFile () + " rather than " + df.getPrimaryFile ()); } 916 dperm[perm[i]] = d; 917 } 918 Set<DataObject> dpermSet = new HashSet<DataObject> (Arrays.asList (dperm)); 919 if (dpermSet.size () != dperm.length) { 920 throw new IllegalArgumentException ("duplicate DataObject's among reordered childen"); } 922 int dindex = 0; 923 for (int i = 0; i < curObjs.length; i++) { 924 if (dpermSet.remove (curObjs[i])) { 925 newObjs[i] = dperm[dindex++]; 926 } else { 927 newObjs[i] = curObjs[i]; 929 } 930 } 931 try { 932 df.setOrder(newObjs); 933 } catch (IOException ex) { 934 Exceptions.attachLocalizedMessage(ex, 935 org.openide.loaders.DataObject.getString("EXC_ReorderFailed")); Exceptions.printStackTrace(ex); 937 } 938 } 939 940 942 public void reorder () { 943 Index.Support.showIndexedCustomizer(this); 944 } 945 946 949 void fireChangeEventAccess () { 950 fireChangeEvent (new ChangeEvent (this)); 951 } 952 953 955 private final class Listener extends Object implements NodeListener { 956 Listener() {} 957 959 public void propertyChange (PropertyChangeEvent ev) { 960 } 961 964 public void nodeDestroyed(NodeEvent ev) { 965 } 966 967 970 public void childrenReordered(NodeReorderEvent ev) { 971 fireChangeEventAccess (); 972 } 973 976 public void childrenRemoved(NodeMemberEvent ev) { 977 fireChangeEventAccess (); 978 } 979 982 public void childrenAdded(NodeMemberEvent ev) { 983 fireChangeEventAccess (); 984 } 985 } 987 } 989 990 992 public abstract static class SortMode extends Object implements Comparator { 993 994 public static final SortMode NONE = new FolderComparator (FolderComparator.NONE); 995 996 997 public static final SortMode NAMES = new FolderComparator (FolderComparator.NAMES); 998 999 1000 public static final SortMode CLASS = new FolderComparator (FolderComparator.CLASS); 1001 1002 1005 public static final SortMode FOLDER_NAMES = new FolderComparator (FolderComparator.FOLDER_NAMES); 1006 1007 1012 public static final SortMode LAST_MODIFIED = new FolderComparator(FolderComparator.LAST_MODIFIED); 1013 1014 1018 public static final SortMode SIZE = new FolderComparator(FolderComparator.SIZE); 1019 1020 1023 void write (FileObject f) throws IOException { 1024 1027 String x; 1028 if (this == FOLDER_NAMES) x = "F"; else if (this == NAMES) x = "N"; else if (this == CLASS) x = "C"; else if (this == LAST_MODIFIED) x = "M"; else if (this == SIZE) x = "S"; else x = "O"; 1035 f.setAttribute (EA_SORT_MODE, x); 1036 } 1037 1038 1040 static SortMode read (FileObject f) { 1041 String x = (String )f.getAttribute (EA_SORT_MODE); 1042 if (x == null || x.length () != 1) return FOLDER_NAMES; 1043 1044 char c = x.charAt (0); 1045 switch (c) { 1046 case 'N': return NAMES; 1047 case 'C': return CLASS; 1048 case 'O': return NONE; 1049 case 'M': return LAST_MODIFIED; 1050 case 'S': return SIZE; 1051 case 'F': 1052 default: 1053 return FOLDER_NAMES; 1054 } 1055 } 1056 } 1057 1058 1059 private static boolean confirmName (String folderName) { 1060 return folderName.indexOf ('/') == -1 && folderName.indexOf ('\\') == -1; 1061 } 1062 1063 1065 private static Image icon2image(String key) { 1066 Object obj = UIManager.get(key); 1067 if (obj instanceof Image ) { 1068 return (Image )obj; 1069 } 1070 1071 if (obj instanceof Icon) { 1072 Icon icon = (Icon)obj; 1073 return Utilities.icon2Image(icon); 1074 } 1075 1076 return null; 1077 } 1078 1079 1080 private static Image [] IMGS = new Image [2]; 1081 1082 static Image findIcon(int index, String k1, String k2) { 1083 if (IMGS[index] != null) { 1084 return IMGS[index]; 1085 } 1086 1087 Image i1 = icon2image(k1); 1088 if (i1 == null) { 1089 i1 = icon2image(k2); 1090 } 1091 1092 IMGS[index] = i1; 1093 return i1; 1094 } 1095 1096 1098 public class FolderNode extends DataNode { 1099 1102 public FolderNode (Children ch) { 1103 super (DataFolder.this, ch); 1104 setIconBaseWithExtension(FOLDER_ICON_BASE); 1105 } 1106 1107 1109 protected FolderNode () { 1110 super (DataFolder.this, new FolderChildren (DataFolder.this)); 1111 setIconBaseWithExtension(FOLDER_ICON_BASE); 1112 } 1113 1114 1115 1120 public Image getIcon (int type) { 1121 Image img = null; 1122 if (type == BeanInfo.ICON_COLOR_16x16) { 1123 img = findIcon(0, "Nb.Explorer.Folder.icon", "Tree.closedIcon"); } 1126 if (img == null) { 1127 img = super.getIcon(type); 1128 } else { 1129 try { 1132 DataObject obj = getDataObject(); 1133 img = obj.getPrimaryFile().getFileSystem(). 1134 getStatus().annotateIcon(img, type, obj.files()); 1135 } catch (FileStateInvalidException e) { 1136 } 1138 } 1139 return img; 1140 } 1141 1142 1147 public Image getOpenedIcon (int type) { 1148 Image img = null; 1149 if (type == BeanInfo.ICON_COLOR_16x16) { 1150 img = findIcon(1, "Nb.Explorer.Folder.openedIcon", "Tree.openIcon"); } 1153 if (img == null) { 1154 img = super.getOpenedIcon(type); 1155 } else { 1156 try { 1159 DataObject obj = getDataObject(); 1160 img = obj.getPrimaryFile().getFileSystem(). 1161 getStatus().annotateIcon(img, type, obj.files()); 1162 } catch (FileStateInvalidException e) { 1163 } 1165 } 1166 return img; 1167 } 1168 1169 @SuppressWarnings ("unchecked") 1170 public Node.Cookie getCookie (Class clazz) { 1171 if (clazz == org.openide.nodes.Index.class || clazz == Index.class) { 1172 try { 1175 if (DataFolder.this.getPrimaryFile().getFileSystem() == 1176 Repository.getDefault().getDefaultFileSystem() || 1177 Boolean.TRUE.equals(DataFolder.this.getPrimaryFile().getAttribute("DataFolder.Index.reorderable"))) { return new Index (DataFolder.this, this); 1179 } 1180 } catch (FileStateInvalidException ex) { 1181 Logger.getLogger(DataFolder.class.getName()).log(Level.WARNING, null, ex); 1182 } 1183 } 1184 return super.getCookie (clazz); 1185 } 1186 1187 1190 protected Sheet createSheet () { 1191 Sheet s = super.createSheet (); 1192 1193 Sheet.Set ss = new Sheet.Set (); 1194 ss.setName (SET_SORTING); 1195 ss.setDisplayName (DataObject.getString ("PROP_sorting")); 1196 ss.setShortDescription (DataObject.getString ("HINT_sorting")); 1197 1198 Node.Property p; 1199 1200 p = new PropertySupport.ReadWrite<SortMode> ( 1201 PROP_SORT_MODE, SortMode.class, 1202 DataObject.getString("PROP_sort"), 1203 DataObject.getString("HINT_sort") 1204 ) { 1205 public SortMode getValue () { 1206 return DataFolder.this.getSortMode (); 1207 } 1208 1209 public void setValue (SortMode o) throws InvocationTargetException { 1210 try { 1211 DataFolder.this.setSortMode (o); 1212 } catch (IOException ex) { 1213 throw new InvocationTargetException (ex); 1214 } 1215 } 1216 1217 public java.beans.PropertyEditor getPropertyEditor () { 1218 return new SortModeEditor (); 1219 } 1220 }; 1221 ss.put (p); 1222 1223 s.put (ss); 1224 return s; 1225 } 1226 1227 1230 public Action getPreferredAction() { 1231 return null; 1232 } 1233 1234 1235 1238 public NewType[] getNewTypes () { 1239 return new NewType[0]; 1240 1249 } 1250 private synchronized FolderRenameHandler getRenameHandler() { 1251 Collection handlers = Lookup.getDefault().lookupAll(FolderRenameHandler.class); 1252 if (handlers.size()==0) 1253 return null; 1254 if (handlers.size()>1) 1255 DataObject.LOG.warning( 1256 "Multiple instances of FolderRenameHandler found in Lookup; only using first one: " + handlers); return (FolderRenameHandler) handlers.iterator().next(); 1258 } 1259 1260 public void setName(String name) { 1261 FolderRenameHandler handler = getRenameHandler(); 1262 if (handler == null) { 1263 super.setName(name); 1264 } else { 1265 handler.handleRename(DataFolder.this, name); 1266 } 1267 } 1268 1269 1277 protected void createPasteTypes (Transferable t, java.util.List <PasteType> s) { 1278 super.createPasteTypes (t, s); 1279 if (getPrimaryFile().canWrite()) { 1280 dataTransferSupport.createPasteTypes (t, s); 1281 } 1282 1283 List<File> files = getDraggedFilesList( t ); 1284 if( null != files && !files.isEmpty() && s.isEmpty() ) { 1285 List<Transferable> transferables = new ArrayList<Transferable>( files.size() ); 1288 for(File f: files) { 1289 Transferable nodeTransferable = createNodeTransferable( f ); 1290 if( null != nodeTransferable ) 1291 transferables.add( nodeTransferable ); 1292 } 1293 ExTransferable.Multi multi = new ExTransferable.Multi( 1294 transferables.toArray(new Transferable[transferables.size()]) ); 1295 super.createPasteTypes (multi, s); 1296 if (getPrimaryFile().canWrite()) { 1297 dataTransferSupport.createPasteTypes (multi, s); 1298 } 1299 } 1300 } 1301 1302 Transferable createNodeTransferable( File f ) { 1303 Transferable result = null; 1304 FileObject fo = FileUtil.toFileObject(FileUtil.normalizeFile(f)); 1305 if( null != fo ) { 1306 try { 1307 DataObject dob = DataObject.find( fo ); 1308 if( null != dob ) { 1309 Node delegate = dob.getNodeDelegate(); 1310 if (!delegate.equals(this)) { 1312 result = dob.getNodeDelegate().clipboardCopy(); 1313 ExClipboard exClipboard = Lookup.getDefault().lookup(ExClipboard.class); 1314 if (exClipboard != null) { 1315 result = exClipboard.convert( result ); 1317 } 1318 } 1319 } 1320 } catch( IOException ioE ) { 1321 Logger.getLogger(DataFolder.class.getName()).log(Level.WARNING, null, ioE); 1322 } 1323 } 1324 return result; 1325 } 1326 1327 private List<File> getDraggedFilesList( Transferable t ) { 1328 try { 1329 if( t.isDataFlavorSupported( DataFlavor.javaFileListFlavor ) ) { 1330 List fileList = (List) t.getTransferData(DataFlavor.javaFileListFlavor); 1332 if( null != fileList ) 1334 return NbCollections.checkedListByCopy((List) t.getTransferData(DataFlavor.javaFileListFlavor), File.class, true); 1335 } else if( t.isDataFlavorSupported( getUriListDataFlavor() ) ) { 1336 String uriList = (String )t.getTransferData( getUriListDataFlavor() ); 1338 return textURIListToFileList( uriList ); 1339 } 1340 } catch( UnsupportedFlavorException ex ) { 1341 Logger.getLogger(DataFolder.class.getName()).log(Level.WARNING, null, ex); 1342 } catch( IOException ex ) { 1343 Logger.getLogger(DataFlavor.class.getName()).log(Level.FINE, null, ex); 1345 } 1346 return null; 1347 } 1348 1349 private DataFlavor getUriListDataFlavor() { 1350 if( null == uriListDataFlavor ) { 1351 try { 1352 uriListDataFlavor = new DataFlavor("text/uri-list;class=java.lang.String"); 1353 } catch( ClassNotFoundException cnfE ) { 1354 throw new AssertionError (cnfE); 1356 } 1357 } 1358 return uriListDataFlavor; 1359 } 1360 1361 private List<File> textURIListToFileList( String data ) { 1362 List<File> list = new ArrayList<File>(1); 1363 for( StringTokenizer st = new StringTokenizer(data, "\r\n"); 1365 st.hasMoreTokens();) { 1366 String s = st.nextToken(); 1367 if( s.startsWith("#") ) { 1368 continue; 1370 } 1371 try { 1372 URI uri = new URI (s); 1373 File file = new File(uri); 1374 list.add( file ); 1375 } catch( java.net.URISyntaxException e ) { 1376 } catch( IllegalArgumentException e ) { 1378 } 1380 } 1381 return list; 1382 } 1383 1384 } 1386 1388 private final class NewFolder extends NewType { 1389 NewFolder() {} 1390 1391 1396 public String getName() { 1397 return DataObject.getString ("CTL_NewFolder"); 1398 } 1399 1400 1403 public HelpCtx getHelpCtx() { 1404 return HelpCtx.DEFAULT_HELP; 1405 } 1406 1407 1410 public void create () throws IOException { 1411 NotifyDescriptor.InputLine input = new NotifyDescriptor.InputLine ( 1412 DataObject.getString ("CTL_NewFolderName"), DataObject.getString ("CTL_NewFolderTitle") 1413 ); 1414 input.setInputText (DataObject.getString ("CTL_NewFolderValue")); 1415 if (DialogDisplayer.getDefault ().notify (input) == NotifyDescriptor.OK_OPTION) { 1416 String folderName = input.getInputText (); 1417 if ("".equals (folderName)) return; 1419 FileObject folder = getPrimaryFile (); 1420 int dotPos = -1; 1421 1422 while ((dotPos = folderName.indexOf (".")) != -1) { String subFolder = folderName.substring (0, dotPos); 1424 folderName = folderName.substring (dotPos + 1); 1425 1426 1427 FileObject existingFile = folder.getFileObject (subFolder); 1428 if (existingFile != null) { 1429 if (!existingFile.isFolder ()) { 1430 DialogDisplayer.getDefault ().notify ( 1431 new NotifyDescriptor.Message ( 1432 NbBundle.getMessage (DataObject.class, 1433 "MSG_FMT_FileExists", 1434 subFolder, folder.getName ()), 1435 NotifyDescriptor.WARNING_MESSAGE 1436 ) 1437 ); 1438 return; 1439 } 1440 folder = existingFile; 1441 } else { 1442 if (! confirmName (subFolder)) { 1443 throw new IOException( 1444 NbBundle.getMessage(DataObject.class, 1445 "EXC_WrongName", subFolder) 1446 ); 1447 } 1448 folder = folder.createFolder (subFolder); 1449 } 1450 } 1451 if (!"".equals (folderName)) { FileObject existingFile = folder.getFileObject (folderName); 1453 if (existingFile != null) { 1454 if (existingFile.isFolder ()) { 1455 DialogDisplayer.getDefault ().notify ( 1456 new NotifyDescriptor.Message ( 1457 NbBundle.getMessage (DataObject.class, 1458 "MSG_FMT_FolderExists", 1459 folderName, folder.getName ()), 1460 NotifyDescriptor.INFORMATION_MESSAGE 1461 ) 1462 ); 1463 } else { 1464 DialogDisplayer.getDefault ().notify ( 1465 new NotifyDescriptor.Message ( 1466 NbBundle.getMessage (DataObject.class, 1467 "MSG_FMT_FileExists", 1468 folderName, folder.getName ()), 1469 NotifyDescriptor.WARNING_MESSAGE 1470 ) 1471 ); 1472 } 1473 return; 1474 } 1475 1476 if (! confirmName (folderName)) { 1477 throw new IOException( 1478 NbBundle.getMessage(DataObject.class, 1479 "EXC_WrongName", folderName ) 1480 ); 1481 } 1482 1483 DataObject created = DataObject.find(folder.createFolder (folderName)); 1484 if (created != null) { 1485 DataLoaderPool.getDefault().fireOperationEvent( 1486 new OperationEvent.Copy (created, DataFolder.this), OperationEvent.TEMPL 1487 ); 1488 } 1489 } 1490 } 1491 } 1492 } 1493 1494 private class Paste extends DataTransferSupport { 1495 Paste() {} 1496 1497 1501 protected DataTransferSupport.PasteTypeExt[] definePasteTypes (int op) { 1502 switch (op) { 1503 case LoaderTransfer.CLIPBOARD_CUT: 1504 return new DataTransferSupport.PasteTypeExt [] { 1505 new DataTransferSupport.PasteTypeExt() { 1506 public String getName () { 1507 return DataObject.getString ("PT_move"); } 1509 public HelpCtx getHelpCtx () { 1510 return new HelpCtx (Paste.class.getName () + ".move"); } 1512 protected boolean handleCanPaste (DataObject obj) { 1513 return obj.isMoveAllowed () && !isParent (getPrimaryFile (), obj.getPrimaryFile ()); 1514 } 1515 protected void handlePaste (DataObject obj) throws IOException { 1516 obj.move (DataFolder.this); 1517 } 1518 1519 1520 protected boolean cleanClipboard() { 1521 return true; 1522 } 1523 1524 1529 1530 private boolean isParent (FileObject fo, FileObject parent) { 1531 File parentFile = FileUtil.toFile(parent); 1532 File foFile = FileUtil.toFile(fo); 1533 1534 if (foFile != null && parentFile != null) { 1535 return isParentFile(foFile, parentFile); 1536 } 1537 1538 try { 1539 if (fo.getFileSystem () != parent.getFileSystem ()) { 1540 return false; 1541 } 1542 } catch (IOException ex) { 1543 } 1544 1545 while (fo != null) { 1546 if (fo.equals (parent)) { 1547 return true; 1548 } 1549 1550 fo = fo.getParent (); 1551 } 1552 1553 return false; 1554 } 1555 } 1556 }; 1557 1558 case LoaderTransfer.CLIPBOARD_COPY: 1559 return new DataTransferSupport.PasteTypeExt[] { 1560 new DataTransferSupport.PasteTypeExt() { 1561 public String getName () { 1562 return DataObject.getString ("PT_copy"); } 1564 public HelpCtx getHelpCtx () { 1565 return new HelpCtx (Paste.class.getName () + ".copy"); } 1567 protected boolean handleCanPaste (DataObject obj) { 1568 return obj.isCopyAllowed (); 1569 } 1570 protected void handlePaste (DataObject obj) throws IOException { 1571 saveIfModified(obj); 1572 obj.copy (DataFolder.this); 1573 } 1574 1575 private void saveIfModified(DataObject obj) throws IOException { 1576 if (obj.isModified()) { 1577 SaveCookie sc = obj.getCookie(SaveCookie.class); 1578 if (sc != null) { 1579 sc.save(); 1580 } 1581 } 1582 } 1583 }, 1584 new DataTransferSupport.PasteTypeExt() { 1585 public String getName () { 1586 return DataObject.getString ("PT_instantiate"); } 1588 public HelpCtx getHelpCtx () { 1589 return new HelpCtx (Paste.class.getName () + ".instantiate"); } 1591 protected boolean handleCanPaste (DataObject obj) { 1592 return obj.isTemplate (); 1593 } 1594 protected void handlePaste (DataObject obj) throws IOException { 1595 obj.createFromTemplate (DataFolder.this); 1596 } 1597 }, 1598 new DataTransferSupport.PasteTypeExt() { 1599 public String getName () { 1600 return DataObject.getString ("PT_shadow"); } 1602 public HelpCtx getHelpCtx () { 1603 return new HelpCtx (Paste.class.getName () + ".shadow"); } 1605 protected boolean handleCanPaste (DataObject obj) { 1606 try { 1608 if (!DataFolder.this.getPrimaryFile().getFileSystem().equals( 1609 Repository.getDefault().getDefaultFileSystem())) { 1610 return false; 1611 } 1612 } catch (FileStateInvalidException ex) { 1613 return false; 1615 } 1616 return obj.isShadowAllowed (); 1617 } 1618 protected void handlePaste (DataObject obj) throws IOException { 1619 obj.createShadow (DataFolder.this); 1620 } 1621 } 1622 }; 1623 } 1624 return new DataTransferSupport.PasteTypeExt[0]; 1625 } 1626 1627 private boolean isParentFile(File foFile, File parentFile) { 1628 boolean retVal = false; 1629 while (foFile != null) { 1630 if (foFile.equals (parentFile)) { 1631 retVal = true; 1632 break; 1633 } 1634 foFile = foFile.getParentFile (); 1635 } 1636 return retVal; 1637 } 1638 1639 1642 protected int [] defineOperations () { 1643 return new int [] { 1644 LoaderTransfer.CLIPBOARD_CUT, 1645 LoaderTransfer.CLIPBOARD_COPY 1646 }; 1647 } 1648 protected void handleCreatePasteTypes (Transferable t, java.util.List <PasteType> s) { 1649 Node node = NodeTransfer.node (t, NodeTransfer.CLIPBOARD_COPY); 1651 1652 if (node != null) { 1654 try { 1655 InstanceCookie cookie = node.getCookie(InstanceCookie.class); 1656 if (cookie != null && java.io.Serializable .class.isAssignableFrom (cookie.instanceClass ())) { 1657 s.add (new DataTransferSupport.SerializePaste (DataFolder.this, cookie)); 1658 s.add (new DataTransferSupport.InstantiatePaste (DataFolder.this, cookie)); 1659 } 1660 } catch (IOException e) { 1661 } catch (ClassNotFoundException e) { 1662 } 1663 } 1664 } 1665 } 1666 1667 1669 private final class ListPCL extends Object implements PropertyChangeListener { 1670 ListPCL() {} 1671 public void propertyChange(java.beans.PropertyChangeEvent ev) { 1672 if (this == DataFolder.this.pcl) { 1673 DataFolder.this.firePropertyChange (PROP_CHILDREN, null, null); 1675 } 1676 } 1677 1678 } 1679} 1680 | Popular Tags |