1 19 20 package org.netbeans.core; 21 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.beans.IntrospectionException ; 25 import java.io.IOException ; 26 import java.io.ObjectInputStream ; 27 import java.io.ObjectOutputStream ; 28 import java.util.ArrayList ; 29 import java.util.Arrays ; 30 import java.util.Collection ; 31 import java.util.Collections ; 32 import java.util.Enumeration ; 33 import java.util.HashMap ; 34 import java.util.HashSet ; 35 import java.util.Iterator ; 36 import java.util.LinkedList ; 37 import java.util.List ; 38 import java.util.Map ; 39 import java.util.Set ; 40 import java.util.logging.Level ; 41 import java.util.logging.Logger ; 42 import javax.swing.Action ; 43 import javax.swing.event.ChangeEvent ; 44 import javax.swing.event.ChangeListener ; 45 import org.netbeans.core.startup.ManifestSection; 46 import org.openide.actions.MoveDownAction; 47 import org.openide.actions.MoveUpAction; 48 import org.openide.actions.PropertiesAction; 49 import org.openide.actions.ReorderAction; 50 import org.openide.actions.ToolsAction; 51 import org.openide.filesystems.FileLock; 52 import org.openide.filesystems.FileObject; 53 import org.openide.filesystems.FileSystem; 54 import org.openide.filesystems.MIMEResolver; 55 import org.openide.filesystems.Repository; 56 import org.openide.loaders.DataLoader; 57 import org.openide.loaders.DataLoaderPool; 58 import org.openide.loaders.InstanceSupport; 59 import org.openide.modules.ModuleInfo; 60 import org.openide.modules.SpecificationVersion; 61 import org.openide.nodes.AbstractNode; 62 import org.openide.nodes.BeanNode; 63 import org.openide.nodes.Children; 64 import org.openide.nodes.Node; 65 import org.openide.util.HelpCtx; 66 import org.openide.util.Lookup; 67 import org.openide.util.LookupEvent; 68 import org.openide.util.LookupListener; 69 import org.openide.util.NbBundle; 70 import org.openide.util.RequestProcessor; 71 import org.openide.util.TopologicalSortException; 72 import org.openide.util.Utilities; 73 import org.openide.util.actions.SystemAction; 74 import org.openide.util.io.NbMarshalledObject; 75 import org.openide.util.io.NbObjectInputStream; 76 import org.openide.util.io.NbObjectOutputStream; 77 78 85 public final class LoaderPoolNode extends AbstractNode { 86 88 private static LoaderPoolNode loaderPoolNode; 89 private static final Logger err = 90 Logger.getLogger("org.netbeans.core.LoaderPoolNode"); 92 private static LoaderChildren myChildren; 93 94 95 private static List <DataLoader> loaders = new ArrayList <DataLoader> (); 96 97 private static Set <DataLoader> modifiedLoaders = new HashSet <DataLoader>(); 98 99 private static Map <String ,DataLoader> names2Loaders = new HashMap <String ,DataLoader>(200); 100 101 private static Map <String ,DataLoader> repNames2Loaders = new HashMap <String ,DataLoader>(200); 102 103 104 private static Map <String ,String []> installBefores = new HashMap <String ,String []> (); 105 106 private static Map <String ,String []> installAfters = new HashMap <String ,String []> (); 107 108 109 private static DataLoader[] loadersArray; 110 111 112 private static boolean installationFinished = false; 113 114 115 private static boolean updatingBatch = false; 116 117 private static boolean updatingBatchUsed = false; 118 119 122 private LoaderPoolNode () { 123 super (new LoaderChildren ()); 124 125 myChildren = (LoaderChildren)getChildren (); 126 127 setName("LoaderPoolNode"); setDisplayName(NbBundle.getMessage(LoaderPoolNode.class, "CTL_LoaderPool")); 129 130 getCookieSet ().add (new Index ()); 131 getCookieSet ().add (new InstanceSupport.Instance (getNbLoaderPool ())); 132 } 133 134 public HelpCtx getHelpCtx () { 135 return new HelpCtx (LoaderPoolNode.class); 136 } 137 138 143 public Action [] getActions(boolean context) { 144 return new Action [] { 145 SystemAction.get(ReorderAction.class), 146 null, 147 SystemAction.get(ToolsAction.class), 148 SystemAction.get(PropertiesAction.class), 149 }; 150 151 } 152 153 public static synchronized void beginUpdates() { 154 updatingBatch = true; 155 updatingBatchUsed = false; 156 } 157 public static synchronized void endUpdates() { 158 if (!updatingBatch) throw new IllegalStateException (); 159 updatingBatch = false; 160 if (updatingBatchUsed) { 161 updatingBatchUsed = false; 162 resort(); 163 } 164 } 165 166 168 public static void waitFinished() { 169 getNbLoaderPool().fireTask.waitFinished(); 170 } 171 172 179 public static void add (ManifestSection.LoaderSection s) throws Exception { 180 DataLoader l = (DataLoader)s.getInstance (); 183 doAdd (l, s); 184 } 185 186 188 static synchronized void doAdd (DataLoader l, ManifestSection.LoaderSection s) throws Exception { 189 if (err.isLoggable(Level.FINE) && s != null) { 190 List before = s.getInstallBefore() == null ? null : Arrays.asList(s.getInstallBefore()); 191 List after = s.getInstallAfter() == null ? null : Arrays.asList(s.getInstallAfter()); 192 err.fine("add: " + l + " repclass: " + l.getRepresentationClass().getName() + " before: " + before + " after: " + after); 193 } 194 Iterator it = loaders.iterator (); 195 Class c = l.getClass(); 196 while (it.hasNext ()) { 197 if (it.next ().getClass () == c) { 198 it.remove (); 199 break; 200 } 201 } 202 loaders.add (l); 203 l.removePropertyChangeListener (getNbLoaderPool ()); 204 l.addPropertyChangeListener (getNbLoaderPool ()); 205 206 String cname = c.getName(); 207 names2Loaders.put(cname, l); 208 repNames2Loaders.put(l.getRepresentationClassName(), l); 209 if (s != null) { 210 String [] ib = s.getInstallBefore(); 211 if (ib != null) installBefores.put(cname, ib); 212 String [] ia = s.getInstallAfter(); 213 if (ia != null) installAfters.put(cname, ia); 214 } 215 if (updatingBatch) { 216 updatingBatchUsed = true; 217 } else { 218 resort (); 219 } 220 } 221 222 223 232 private static synchronized void resort () { 233 Map <DataLoader,List <DataLoader>> deps = new HashMap <DataLoader,List <DataLoader>>(); 235 add2Deps(deps, installBefores, true); 236 add2Deps(deps, installAfters, false); 237 if (err.isLoggable(Level.FINE)) { 238 err.fine("Before sort: " + loaders); 239 } 240 241 try { 242 loaders = Utilities.topologicalSort(loaders, deps); 243 if (err.isLoggable(Level.FINE)) { 244 err.fine("After sort: " + loaders); 245 } 246 } catch (TopologicalSortException ex) { 247 err.log(Level.WARNING, null, ex); 248 err.warning("Contradictory loader ordering: " + deps); } 250 update (); 251 } 252 260 private static void add2Deps(Map <DataLoader,List <DataLoader>> deps, Map orderings, boolean before) { 261 Iterator it = orderings.entrySet().iterator(); 262 while (it.hasNext()) { 263 Map.Entry e = (Map.Entry ) it.next(); 264 String loaderClassName = (String ) e.getKey(); 265 DataLoader l = names2Loaders.get(loaderClassName); 266 267 if (l == null) { 268 throw new IllegalStateException ("No such loader: " + loaderClassName); } 270 String [] repClassNames = (String []) e.getValue(); 271 272 if (repClassNames == null) { 273 throw new IllegalStateException ("Null Install-" + (before ? "Before" : "After") + " for " + loaderClassName); } 275 for (int i = 0; i < repClassNames.length; i++) { 276 String repClassName = repClassNames[i]; 277 DataLoader l2 = repNames2Loaders.get(repClassName); 278 279 if (l2 != null) { 280 if (before) { 281 addDep(deps, l, l2); 282 } 283 else { 284 addDep(deps, l2, l); 285 } 286 } 287 else { 288 l2 = names2Loaders.get(repClassName); 289 if (l2 != null) { 290 warn(loaderClassName, repClassName, 291 l2.getRepresentationClassName()); 292 } 293 } 294 } 295 } 296 } 297 303 private static void addDep(Map <DataLoader,List <DataLoader>> deps, DataLoader a, DataLoader b) { 304 List <DataLoader> l = deps.get(a); 305 if (l == null) { 306 deps.put(a, l = new LinkedList <DataLoader>()); 307 } 308 if (!l.contains(b)) { 309 l.add(b); 310 } 311 } 312 316 private static void warn(String yourLoader, String otherLoader, String otherRepn) { 317 err.warning("Warning: a possible error in the manifest containing " + yourLoader + " was found."); err.warning("The loader specified an Install-{After,Before} on " + otherLoader + ", but this is a DataLoader class."); err.warning("Probably you wanted " + otherRepn + " which is the loader's representation class."); } 321 322 324 static void installationFinished () { 325 installationFinished = true; 326 327 if (myChildren != null) { 328 myChildren.update (); 329 } 330 } 331 332 335 static synchronized boolean isModified (DataLoader l) { 336 return modifiedLoaders.contains (l); 337 } 338 339 342 private static synchronized void writePool (ObjectOutputStream oos) 343 throws IOException { 344 if (err.isLoggable(Level.FINE)) err.fine("writePool"); 345 oos.writeObject (new HashMap ()); 347 oos.writeObject (new HashMap ()); 348 349 Collection modules = Lookup.getDefault().lookupAll(ModuleInfo.class); 352 Iterator it = loaders.iterator (); 353 354 while (it.hasNext ()) { 355 DataLoader l = (DataLoader)it.next (); 356 357 if (!isModified (l)) { 358 String c = l.getClass().getName(); 360 if (err.isLoggable(Level.FINE)) err.fine("writing unmodified " + c); 361 oos.writeObject("=" + c); continue; 364 } 365 366 NbMarshalledObject obj; 367 try { 368 obj = new NbMarshalledObject (l); 369 } catch (IOException ex) { 370 err.log(Level.WARNING, null, ex); 371 obj = null; 372 } 373 374 if (obj != null) { 375 if (err.isLoggable(Level.FINE)) err.fine("writing modified " + l.getClass().getName()); 376 Class c = l.getClass(); 378 Iterator mit = modules.iterator(); 379 boolean found = false; 380 while (mit.hasNext()) { 381 ModuleInfo m = (ModuleInfo)mit.next(); 382 if (m.isEnabled() && m.owns(c)) { 383 if (err.isLoggable(Level.FINE)) err.fine("belongs to module: " + m.getCodeNameBase()); 384 oos.writeObject(m.getCodeNameBase()); 385 int r = m.getCodeNameRelease(); 386 oos.writeInt(r); SpecificationVersion v = m.getSpecificationVersion(); 388 if (v != null) { 389 oos.writeObject(v.toString()); 390 } else { 391 oos.writeObject(null); 392 } 393 found = true; 394 break; 395 } 396 } 397 if (!found) { 398 if (err.isLoggable(Level.FINE)) err.fine("does not belong to any module"); 399 } 403 oos.writeObject (obj); 404 } 405 } 406 if (err.isLoggable(Level.FINE)) err.fine("writing null"); 407 oos.writeObject (null); 408 409 Enumeration e = getNbLoaderPool ().allLoaders (); 411 while (e.hasMoreElements ()) { 412 DataLoader l = (DataLoader) e.nextElement (); 413 if (loaders.contains (l)) continue; 414 if (!isModified (l)) { 415 String c = l.getClass().getName(); 417 if (err.isLoggable(Level.FINE)) err.fine("skipping unmodified " + c); 418 continue; 419 } 420 NbMarshalledObject obj; 421 try { 422 obj = new NbMarshalledObject (l); 423 } catch (IOException ex) { 424 err.log(Level.WARNING, null, ex); 425 obj = null; 426 } 427 if (obj != null) { 428 if (err.isLoggable(Level.FINE)) err.fine("writing " + l.getClass().getName()); 429 oos.writeObject (obj); 431 } 432 } 433 if (err.isLoggable(Level.FINE)) err.fine("writing null"); 434 oos.writeObject (null); 435 436 if (err.isLoggable(Level.FINE)) err.fine("done writing"); 437 } 438 439 442 private static synchronized void readPool (ObjectInputStream ois) 443 throws IOException , ClassNotFoundException { 444 ois.readObject (); 445 ois.readObject (); 446 447 HashSet <Class > classes = new HashSet <Class > (); 448 LinkedList <DataLoader> l = new LinkedList <DataLoader> (); 449 450 Iterator <? extends ModuleInfo> mit = Lookup.getDefault().lookupAll(ModuleInfo.class).iterator(); 451 Map <String ,ModuleInfo> modules = new HashMap <String ,ModuleInfo>(); 452 while (mit.hasNext()) { 453 ModuleInfo m = mit.next(); 454 modules.put(m.getCodeNameBase(), m); 455 } 456 457 for (;;) { 458 Object o1 = ois.readObject(); 459 460 if (o1 == null) { 461 if (err.isLoggable(Level.FINE)) 462 err.fine("reading null"); 463 break; 464 } 465 NbMarshalledObject obj; 466 467 if (o1 instanceof String ) { 468 String name = (String )o1; 469 if (name.length() > 0 && name.charAt(0) == '=') { String cname = name.substring(1); 472 DataLoader dl = names2Loaders.get(cname); 473 474 if (dl != null) { 475 if (err.isLoggable(Level.FINE)) 476 err.fine("reading unmodified " + cname); 477 l.add(dl); 478 classes.add(dl.getClass()); 479 } 480 else { 481 if (err.isLoggable(Level.FINE)) 483 err.fine("skipping unmodified nonexistent " + cname); 484 } 485 continue; 486 } 487 int rel = ois.readInt(); 489 String spec = (String ) ois.readObject(); 490 491 obj = (NbMarshalledObject) ois.readObject(); 492 ModuleInfo m = modules.get(name); 493 494 if (m == null) { 495 if (err.isLoggable(Level.FINE)) 496 err.fine("No known module " + name + ", skipping loader"); 497 continue; 498 } 499 if (!m.isEnabled()) { 500 if (err.isLoggable(Level.FINE)) 501 err.fine("Module " + name + 502 " is disabled, skipping loader"); 503 continue; 504 } 505 if (m.getCodeNameRelease() < rel) { 506 if (err.isLoggable(Level.FINE)) 507 err.fine("Module " + name + " is too old (major vers.), skipping loader"); 508 continue; 509 } 510 if (spec != null) { 511 SpecificationVersion v = m.getSpecificationVersion(); 512 513 if (v == null || 514 v.compareTo(new SpecificationVersion(spec)) < 0) { 515 if (err.isLoggable(Level.FINE)) 516 err.fine("Module " + name + " is too old (spec. vers.), skipping loader"); 517 continue; 518 } 519 } 520 if (err.isLoggable(Level.FINE)) 521 err.fine("Module " + name + 522 " is OK, will try to restore loader"); 523 } 524 else { 525 obj = (NbMarshalledObject) o1; 527 } 528 Exception t = null; 529 530 try { 531 DataLoader loader = (DataLoader) obj.get(); 532 533 if (loader == null) { 534 continue; 537 } 538 Class clazz = loader.getClass(); 539 540 if (err.isLoggable(Level.FINE)) 541 err.fine("reading modified " + clazz.getName()); 542 l.add(loader); 543 classes.add(clazz); 544 } 545 catch (IOException ex) { 546 t = ex; 547 } 548 catch (ClassNotFoundException ex) { 549 t = ex; 550 } 551 } 552 553 for (;;) { 555 NbMarshalledObject obj = (NbMarshalledObject) ois.readObject (); 556 if (obj == null) { 557 if (err.isLoggable(Level.FINE)) err.fine("reading null"); 558 break; 559 } 560 Exception t = null; 561 try { 562 DataLoader loader = (DataLoader) obj.get (); 564 if (err.isLoggable(Level.FINE)) err.fine("reading " + loader.getClass().getName()); 565 } catch (IOException ex) { 566 t = ex; 567 } catch (ClassNotFoundException ex) { 568 t = ex; 569 } 570 } 571 572 if (err.isLoggable(Level.FINE)) err.fine("done reading"); 573 574 582 Iterator it = loaders.iterator (); 583 while (it.hasNext ()) { 584 DataLoader loader = (DataLoader)it.next (); 585 if (!classes.contains (loader.getClass ())) { 586 l.add (loader); 587 } 588 } 589 if (l.size() > new HashSet <DataLoader>(l).size()) throw new IllegalStateException ("Duplicates in " + l); 591 loaders = l; 592 resort (); 596 597 } 598 599 public static void store() throws IOException { 601 FileObject ser = getLoaderPoolStorage(true); 602 FileLock lock = ser.lock(); 603 try { 604 ObjectOutputStream oos = new NbObjectOutputStream(ser.getOutputStream(lock)); 605 try { 606 NbObjectOutputStream.writeSafely(oos, getNbLoaderPool()); 607 } finally { 608 oos.close(); 609 } 610 } finally { 611 lock.releaseLock(); 612 } 613 } 614 public static void load() throws IOException { 615 FileObject ser = getLoaderPoolStorage(false); 616 if (ser != null) { 617 ObjectInputStream ois = new NbObjectInputStream(ser.getInputStream()); 618 try { 619 NbObjectInputStream.readSafely(ois); 620 } finally { 621 ois.close(); 622 } 623 } 624 } 625 private static final String LOADER_POOL_NAME = "loaders.ser"; public static FileObject getLoaderPoolStorage(boolean create) throws IOException { 627 FileSystem sfs = Repository.getDefault().getDefaultFileSystem(); 628 FileObject fo = sfs.findResource(LOADER_POOL_NAME); 629 if (fo == null && create) { 630 fo = sfs.getRoot().createData(LOADER_POOL_NAME); 631 } 632 return fo; 633 } 634 635 636 638 private static synchronized void update () { 639 if (err.isLoggable(Level.FINE)) err.fine("update"); 640 loadersArray = null; 642 643 NbLoaderPool lp = getNbLoaderPool(); 644 if (lp != null && installationFinished) { 645 lp.superFireChangeEvent(); 646 } 647 648 if (lp != null) { 649 Enumeration e = lp.allLoaders(); 650 while (e.hasMoreElements()) { 651 DataLoader l = (DataLoader)e.nextElement(); 652 l.removePropertyChangeListener(lp); 654 l.addPropertyChangeListener(lp); 655 } 656 } 657 } 658 659 660 670 public static synchronized boolean remove (DataLoader dl) { 671 if (loaders.remove (dl)) { 672 if (err.isLoggable(Level.FINE)) err.fine("remove: " + dl); 673 String cname = dl.getClass().getName(); 674 names2Loaders.remove(cname); 675 repNames2Loaders.remove(dl.getRepresentationClassName()); 676 installBefores.remove(cname); 677 installAfters.remove(cname); 678 dl.removePropertyChangeListener (getNbLoaderPool ()); 679 680 if (updatingBatch) { 681 updatingBatchUsed = true; 682 } else { 683 resort (); 684 } 685 modifiedLoaders.remove(dl); 686 return true; 687 } 688 return false; 689 } 690 691 696 public static synchronized LoaderPoolNode getLoaderPoolNode () { 697 if (loaderPoolNode == null) 698 loaderPoolNode = new LoaderPoolNode(); 699 return loaderPoolNode; 700 } 701 702 707 public static synchronized NbLoaderPool getNbLoaderPool () { 708 if (nbLoaderPool == null) { 709 nbLoaderPool = (NbLoaderPool)DataLoaderPool.getDefault (); 710 } 711 return nbLoaderPool; 712 } 713 private static NbLoaderPool nbLoaderPool = null; 714 715 716 717 718 719 private static class LoaderPoolItemNode extends BeanNode<DataLoader> { 720 721 722 boolean isSystem; 723 724 730 public LoaderPoolItemNode(DataLoader loader) throws IntrospectionException { 731 super(loader); 732 setSynchronizeName (false); 733 String displayName = getDisplayName(); 734 setName(loader.getClass().getName()); 735 isSystem = ! loaders.contains (loader); 736 if (isSystem) { 737 setDisplayName(NbBundle.getMessage(LoaderPoolNode.class, "LBL_system_data_loader", displayName)); 738 } else { 739 setDisplayName(displayName); 740 } 741 } 742 743 748 public Action [] getActions(boolean context) { 749 if (isSystem) 750 return new Action [] { 751 SystemAction.get(ToolsAction.class), 752 SystemAction.get(PropertiesAction.class), 753 }; 754 else 755 return new Action [] { 756 SystemAction.get(MoveUpAction.class), 757 SystemAction.get(MoveDownAction.class), 758 null, 759 SystemAction.get(ToolsAction.class), 760 SystemAction.get(PropertiesAction.class), 761 }; 762 } 763 764 766 public Action getPreferredAction() { 767 return SystemAction.get (PropertiesAction.class); 768 } 769 770 773 public boolean canDestroy () { 774 return false; 775 } 776 777 779 public boolean canCopy () { 780 return false; 781 } 782 783 785 public boolean canCut () { 786 return false; 787 } 788 789 public boolean canRename () { 790 return false; 791 } 792 793 public HelpCtx getHelpCtx () { 794 HelpCtx help = super.getHelpCtx(); 795 if (help == null || help.getHelpID() == null || help.getHelpID().equals(BeanNode.class.getName())) { 796 help = new HelpCtx (LoaderPoolItemNode.class); 797 } 798 return help; 799 } 800 } 802 806 private static final class LoaderChildren extends Children.Keys<DataLoader> 807 implements ChangeListener { 808 public LoaderChildren () { 809 update (); 810 getNbLoaderPool().addChangeListener(this); 811 } 812 813 814 public void update () { 815 setKeys(Collections.list(getNbLoaderPool().allLoaders())); 816 } 817 818 820 protected Node[] createNodes(DataLoader loader) { 821 try { 822 return new Node[] {new LoaderPoolItemNode(loader)}; 823 } catch (IntrospectionException e) { 824 err.log(Level.WARNING, null, e); 825 return new Node[] { }; 826 } 827 } 828 829 public void stateChanged(ChangeEvent e) { 830 update(); 831 } 832 833 } 835 841 public static final class NbLoaderPool extends DataLoaderPool 842 implements PropertyChangeListener , Runnable , LookupListener { 843 private static final long serialVersionUID =-8488524097175567566L; 844 845 private transient RequestProcessor.Task fireTask; 846 847 private transient Lookup.Result mimeResolvers; 848 private static RequestProcessor rp = new RequestProcessor("Refresh Loader Pool"); 850 public NbLoaderPool() { 851 fireTask = rp.create(this, true); 852 mimeResolvers = Lookup.getDefault().lookupResult(MIMEResolver.class); 853 mimeResolvers.addLookupListener(this); 854 } 855 856 858 protected Enumeration <DataLoader> loaders () { 859 860 864 DataLoader[] arr = loadersArray; 865 if (arr == null) { 866 synchronized (LoaderPoolNode.class) { 867 arr = loadersArray = loaders.toArray (new DataLoader[loaders.size()]); 868 } 869 } 870 return org.openide.util.Enumerations.array (arr); 871 } 872 873 875 public void propertyChange (PropertyChangeEvent ev) { 876 DataLoader l = (DataLoader)ev.getSource(); 877 String prop = ev.getPropertyName (); 878 if (DataLoader.PROP_ACTIONS.equals (prop) && ev.getNewValue () == null) { 879 return; 881 } 882 modifiedLoaders.add(l); 883 if (err.isLoggable(Level.FINE)) err.fine("Got change in " + l.getClass().getName() + "." + prop); 884 if (DataLoader.PROP_ACTIONS.equals (prop) || DataLoader.PROP_DISPLAY_NAME.equals (prop)) 885 return; if (installationFinished) { 887 superFireChangeEvent (); 888 } 889 } 890 891 896 void superFireChangeEvent () { 897 err.fine("Change in loader pool scheduled"); fireTask.schedule (1000); 899 } 900 901 902 public void run () { 903 err.fine("going to fire change in loaders"); super.fireChangeEvent(new ChangeEvent (this)); 905 err.fine("change event fired"); } 907 908 909 911 private void writeObject (ObjectOutputStream oos) throws IOException { 912 LoaderPoolNode.writePool (oos); 913 } 914 915 917 private void readObject (ObjectInputStream ois) 918 throws IOException , ClassNotFoundException { 919 LoaderPoolNode.readPool (ois); 920 } 921 922 924 private Object readResolve () { 925 return getNbLoaderPool (); 926 } 927 928 public void resultChanged(LookupEvent ev) { 929 if (org.netbeans.core.startup.Main.isInitialized()) { 930 superFireChangeEvent(); 931 } 932 } 933 } 935 937 private final class Index extends org.openide.nodes.Index.Support { 938 939 Index() {} 940 941 945 public Node[] getNodes () { 946 Enumeration e = getChildren ().nodes (); 947 List <Node> l = new ArrayList <Node> (); 948 while (e.hasMoreElements ()) { 949 LoaderPoolItemNode node = (LoaderPoolItemNode) e.nextElement (); 950 if (! node.isSystem) l.add (node); 951 } 952 return l.toArray (new Node[l.size ()]); 953 } 954 955 958 public int getNodesCount () { 959 return getNodes ().length; 960 } 961 962 965 public void reorder (int[] perm) { 966 synchronized (LoaderPoolNode.class) { 967 DataLoader[] arr = loaders.toArray (new DataLoader[loaders.size()]); 968 969 if (arr.length == perm.length) { 970 DataLoader[] target = new DataLoader[arr.length]; 971 for (int i = 0; i < arr.length; i++) { 972 if (target[perm[i]] != null) { 973 throw new IllegalArgumentException (); 974 } 975 target[perm[i]] = arr[i]; 976 } 977 978 loaders = new ArrayList <DataLoader> (Arrays.asList (target)); 979 update (); 980 } else { 981 throw new IllegalArgumentException (); 982 } 983 } 984 } 985 986 } 988 } 989 | Popular Tags |