1 19 20 package org.netbeans.modules.autoupdate.catalog; 21 22 import java.awt.Component ; 23 import java.util.logging.Logger ; 24 import org.netbeans.core.NbTopManager; 25 import org.netbeans.core.startup.*; 26 import org.netbeans.*; 27 import java.util.*; 28 import javax.swing.SwingUtilities ; 29 import org.openide.modules.SpecificationVersion; 30 import java.io.File ; 31 import java.beans.*; 32 import org.openide.*; 33 import java.io.IOException ; 34 import java.util.logging.Level ; 35 import org.openide.util.*; 36 37 43 public final class ModuleBean implements Runnable , PropertyChangeListener { 44 45 private static final Logger err = Logger.getLogger("org.netbeans.modules.autoupdate.catalog.ModuleBean"); 47 private final Module module; 48 49 private String codeName; 50 private String codeNameBase; 51 private String specVers; 52 private String implVers; 53 private String buildVers; 54 private String [] provides; 55 private File jar; 56 private boolean enabled; 57 private boolean reloadable; 58 private boolean autoload; 59 private boolean eager; 60 private boolean problematic; 61 private String [] problemDescriptions; 62 private String displayName; 63 private String shortDescription; 64 private String longDescription; 65 private String category; 66 private String classpath; 67 68 69 private ModuleBean(Module m) { 70 module = m; 71 loadProps(); 72 module.addPropertyChangeListener(WeakListeners.propertyChange(this, module)); 73 } 74 75 76 public Module getModule() { 77 return module; 78 } 79 80 private void loadProps() { 81 if (SwingUtilities.isEventDispatchThread()) throw new IllegalStateException (); 82 err.log(Level.FINE, "loadProps: module=" + module); 83 if (! module.isValid()) { 84 err.log(Level.FINE, "invalid, forget it..."); 85 return; 86 } 87 codeName = module.getCodeName(); 89 codeNameBase = module.getCodeNameBase(); 90 SpecificationVersion sv = module.getSpecificationVersion(); 91 specVers = (sv == null ? null : sv.toString()); 92 implVers = module.getImplementationVersion (); 93 buildVers = module.getBuildVersion (); 94 provides = module.getProvides(); 95 jar = module.getJarFile(); 96 enabled = module.isEnabled(); 97 reloadable = module.isReloadable(); 98 autoload = module.isAutoload(); 99 eager = module.isEager(); 100 Set problems = module.getProblems(); 101 problematic = !problems.isEmpty(); 102 if (problematic) { 103 problemDescriptions = new String [problems.size()]; 104 Iterator it = problems.iterator(); 105 int i = 0; 106 while (it.hasNext()) { 107 problemDescriptions[i++] = NbProblemDisplayer.messageForProblem(module, it.next()); 108 } 109 } else { 110 problemDescriptions = null; 111 } 112 err.log (Level.FINE, "IZ #82480: Module.getJarFile() " + module.getJarFile () + (module.getJarFile () != null ? " exists " + Boolean.toString (module.getJarFile ().exists ()) : "")); displayName = module.getDisplayName(); 115 shortDescription = (String )module.getLocalizedAttribute("OpenIDE-Module-Short-Description"); longDescription = (String )module.getLocalizedAttribute("OpenIDE-Module-Long-Description"); category = (String )module.getLocalizedAttribute("OpenIDE-Module-Display-Category"); classpath = NbTopManager.getUninitialized().getModuleSystem().getEffectiveClasspath(module); 119 } 120 121 122 public String getCodeName() { 123 return codeName; 124 } 125 126 127 public String getCodeNameBase() { 128 return codeNameBase; 129 } 130 131 132 public String getSpecificationVersion() { 133 return specVers; 134 } 135 136 137 public String getImplementationVersion() { 138 return implVers; 139 } 140 141 142 public String getBuildVersion() { 143 return buildVers; 144 } 145 146 147 public String [] getProvides() { 148 return provides; 149 } 150 151 152 public File getJar() { 153 return jar; 154 } 155 156 157 public File getCluster() { 158 if (jar != null) { 159 File p = jar.getParentFile(); 160 if (p != null && p.getName().matches("eager|autoload")) { p = p.getParentFile(); 162 } 163 if (p != null && p.getName().matches("modules|lib|core")) { return p.getParentFile(); 165 } 166 } 167 return null; 168 } 169 170 171 public boolean isEnabled() { 172 return enabled; 173 } 174 175 176 public void setEnabled(boolean e) { 177 if (enabled == e) return; 178 if (jar == null || autoload || eager || problematic) throw new IllegalStateException (); 179 err.log(Level.FINE, "setEnabled: module=" + module + " enabled=" + e); 180 enabled = e; supp.firePropertyChange("enabled", null, null); Update u = new Update(e ? "enable" : "disable", module); AllModulesBean.getDefault().update(u); 184 } 185 186 187 public boolean isAutoload() { 188 return autoload; 189 } 190 191 192 public boolean isEager() { 193 return eager; 194 } 195 196 197 public boolean isReloadable() { 198 return reloadable; 199 } 200 201 202 public void setReloadable(boolean r) { 203 if (reloadable == r) return; 205 err.log(Level.FINE, 206 "setReloadable: module=" + module + " reloadable=" + r); 207 reloadable = r; supp.firePropertyChange("reloadable", null, null); Update u = new Update(r ? "makeReloadable" : "makeUnreloadable", module); AllModulesBean.getDefault().update(u); 211 } 212 213 214 public void delete() { 215 if (jar == null) throw new IllegalStateException (); 216 err.log(Level.FINE, "delete: module=" + module); 217 Update u = new Update("delete", module); AllModulesBean.getDefault().update(u); 219 } 220 221 222 public boolean isProblematic() { 223 return problematic; 224 } 225 226 233 public String [] getProblemDescriptions() { 234 return problemDescriptions; 235 } 236 237 238 public String getDisplayName() { 239 return displayName; 240 } 241 242 243 public String getShortDescription() { 244 return shortDescription; 245 } 246 247 248 public String getLongDescription() { 249 return longDescription; 250 } 251 252 253 public String getCategory() { 254 return category; 255 } 256 257 262 public String getEffectiveClasspath() { 263 return classpath; 264 } 265 266 private final PropertyChangeSupport supp = new PropertyChangeSupport(this); 267 268 269 public void addPropertyChangeListener(PropertyChangeListener l) { 270 supp.removePropertyChangeListener(l); 271 supp.addPropertyChangeListener(l); 272 } 273 274 275 public void removePropertyChangeListener(PropertyChangeListener l) { 276 supp.removePropertyChangeListener(l); 277 } 278 279 public void propertyChange(PropertyChangeEvent evt) { 280 if (SwingUtilities.isEventDispatchThread()) throw new IllegalStateException (); 281 err.log(Level.FINE, "got changes: module=" + module + " evt=" + evt); 283 if ( evt != null && Module.PROP_CLASS_LOADER.equals(evt.getPropertyName())) { 284 err.log(Level.FINE, "ignoring PROP_CLASS_LOADER"); 285 return; 287 } 288 loadProps(); 289 SwingUtilities.invokeLater(this); 290 } 291 292 public void run() { 293 if (! SwingUtilities.isEventDispatchThread()) throw new IllegalStateException (); 294 err.log(Level.FINE, "firing changes: module=" + module); 296 supp.firePropertyChange(null, null, null); 297 ModuleSelectionPanel.getGUI (false).setWaitingState (false, false); 298 } 299 300 303 public boolean equals(Object o) { 304 return (o instanceof ModuleBean) && 305 codeNameBase.equals(((ModuleBean)o).codeNameBase); 306 } 307 308 public int hashCode() { 309 return 35632846 ^ codeNameBase.hashCode(); 310 } 311 312 public String toString() { 313 return "ModuleBean[" + codeNameBase + "]"; } 315 316 public static final class AllModulesBean implements Runnable , PropertyChangeListener, Comparator { 317 318 private static AllModulesBean deflt = null; 319 320 public static synchronized AllModulesBean getDefault() { 321 if (deflt == null) deflt = new AllModulesBean(); 322 return deflt; 323 } 324 private AllModulesBean() {} 325 326 private final ModuleManager mgr = NbTopManager.getUninitialized().getModuleSystem().getManager(); 327 private final Events ev = NbTopManager.getUninitialized().getModuleSystem().getEvents(); 328 329 private final PropertyChangeSupport supp = new PropertyChangeSupport(this); 330 331 332 public void addPropertyChangeListener(PropertyChangeListener l) { 333 supp.removePropertyChangeListener(l); 334 supp.addPropertyChangeListener(l); 335 } 336 337 338 public void removePropertyChangeListener(PropertyChangeListener l) { 339 supp.removePropertyChangeListener(l); 340 } 341 342 private ModuleBean[] modules = null; 343 344 private Task recalcTask = null; 345 346 347 public synchronized ModuleBean[] getModules() { 348 err.log(Level.FINE, 349 "getModules: modules count=" + 350 (modules == null ? "null" 351 : String.valueOf(modules.length))); 352 if (modules == null) { 353 recalcTask = RequestProcessor.getDefault().post(new Reader()); 354 modules = new ModuleBean[0]; 355 return modules; 356 } else { 357 return modules; 358 } 359 } 360 361 366 public synchronized Task waitForModules() { 367 getModules(); 368 if (recalcTask != null) { 369 return recalcTask; 370 } else { 371 return Task.EMPTY; 372 } 373 } 374 375 376 public void create(File jar, boolean reloadable) { 377 err.log(Level.FINE, "create: jar=" + jar); 378 Update u = new Update(reloadable ? "createReloadable" : "create", jar); update(u); 380 } 381 382 private class Reader implements Runnable { 383 private boolean theother = false; 384 Reader() {} 385 388 public void run() { 389 if (SwingUtilities.isEventDispatchThread()) throw new IllegalStateException (); 390 if (! theother) { 391 err.log(Level.FINE, "will load modules in read mutex..."); 392 Reader r = new Reader(); 393 r.theother = true; 394 mgr.mutex().readAccess(r); 395 return; 396 } 397 err.log(Level.FINE, "first time, finding module list"); 398 Set modulesSet = mgr.getModules(); 400 ModuleBean[] _modules = new ModuleBean[modulesSet.size()]; 401 Iterator it = modulesSet.iterator(); 402 int i = 0; 403 while (it.hasNext()) { 404 Module m = (Module)it.next(); 405 _modules[i++] = new ModuleBean(m); 406 } 407 synchronized (AllModulesBean.this) { 408 modules = _modules; 409 recalcTask = null; 410 } 411 mgr.addPropertyChangeListener(org.openide.util.WeakListeners.propertyChange(AllModulesBean.this, mgr)); 413 SwingUtilities.invokeLater(AllModulesBean.this); 415 } 416 } 417 418 public void run() { 419 if (! SwingUtilities.isEventDispatchThread()) throw new IllegalStateException (); 420 err.log(Level.FINE, "in event thread, will fire changes"); 421 supp.firePropertyChange(null, null, null); 424 } 425 426 public void propertyChange(PropertyChangeEvent evt) { 427 if (SwingUtilities.isEventDispatchThread()) throw new IllegalStateException (); 428 err.log(Level.FINE, "got changes: evt=" + evt); 429 ModuleSelectionPanel.getGUI (false).setWaitingState (true, true); 430 if (ModuleManager.PROP_MODULES.equals(evt.getPropertyName())) { 431 Map modules2Beans = new HashMap(modules.length * 4 / 3 + 1); 433 for (int i = 0; i < modules.length; i++) { 434 modules2Beans.put(modules[i].getModule(), modules[i]); 435 } 436 Set modulesSet = mgr.getModules(); 437 ModuleBean[] themodules = new ModuleBean[modulesSet.size()]; 438 Iterator it = modulesSet.iterator(); 439 int i = 0; 440 while (it.hasNext()) { 441 Module m = (Module)it.next(); 442 ModuleBean existing = (ModuleBean)modules2Beans.get(m); 443 if (existing == null) existing = new ModuleBean(m); 444 themodules[i++] = existing; 445 } 446 synchronized (this) { 447 modules = themodules; 448 } 449 SwingUtilities.invokeLater(this); 451 } 452 } 453 454 private final List<Update> updates = new LinkedList<Update>(); 455 456 private boolean paused = false; 457 458 private Runnable updater = new Updater(); 459 460 private RequestProcessor.Task updaterTask = new RequestProcessor ("module-bean-updater").create (updater); 461 462 463 public void pause() { 464 err.log(Level.FINE, "pause"); 465 paused = true; 466 } 467 468 469 public void resume() { 470 err.log(Level.FINE, "resume"); 471 paused = false; 472 updaterTask.schedule (0); 473 } 474 475 476 public void cancel() { 477 err.log(Level.FINE, "cancel"); 478 synchronized (updates) { 479 updates.clear(); 480 } 481 paused = false; 482 supp.firePropertyChange("pending", null, null); } 484 485 486 public boolean isPending() { 487 synchronized (updates) { 488 return ! updates.isEmpty(); 489 } 490 } 491 492 495 void update(Update u) { 496 synchronized (updates) { 497 boolean runme = updates.isEmpty(); 499 updates.add(u); 500 err.log(Level.FINE, "pending updates: " + updates); 501 if (runme) { 502 updaterTask.schedule (0); 503 } 504 } 505 supp.firePropertyChange("pending", null, null); } 507 508 private class Updater implements Runnable { 509 Updater() {} 510 513 public void run() { 514 if (SwingUtilities.isEventDispatchThread()) throw new IllegalStateException (); 515 if (! mgr.mutex ().isWriteAccess ()) { 516 err.log(Level.FINE, "saving all documents..."); 517 org.openide.LifecycleManager.getDefault ().saveAll (); 518 err.log(Level.FINE, "will run updates in write mutex..."); 519 mgr.mutex().writeAccess(this); 520 return; 521 } 522 try { 523 if (paused) { 524 err.log(Level.FINE, "run updates, but paused"); 525 return; 526 } 527 ModuleSelectionPanel.getGUI (false).setWaitingState (true, true); 528 Set toEnable = new HashSet(); Set toDisable = new HashSet(); Set toMakeReloadable = new HashSet(); Set toMakeUnreloadable = new HashSet(); Set toDelete = new HashSet(); Set toCreate = new HashSet(); Set toCreateReloable = new HashSet(); Iterator it; 536 synchronized (updates) { 537 if (updates.isEmpty()) { 538 err.log(Level.FINE, "run updates, but empty"); 539 return; 540 } 541 err.log(Level.FINE, "run updates: " + updates); 542 it = new LinkedList(updates).iterator(); 543 updates.clear(); 544 } 545 while (it.hasNext()) { 546 Update u = (Update)it.next(); 547 if (u.command.equals("enable")) { if (toDelete.contains(u.arg)) throw new IllegalStateException (); 549 toDisable.remove(u.arg); 550 toEnable.add(u.arg); 551 } else if (u.command.equals("disable")) { if (toDelete.contains(u.arg)) throw new IllegalStateException (); 553 toEnable.remove(u.arg); 554 toDisable.add(u.arg); 555 } else if (u.command.equals("makeReloadable")) { if (toDelete.contains(u.arg)) throw new IllegalStateException (); 557 toMakeUnreloadable.remove(u.arg); 558 toMakeReloadable.add(u.arg); 559 } else if (u.command.equals("makeUnreloadable")) { if (toDelete.contains(u.arg)) throw new IllegalStateException (); 561 toMakeReloadable.remove(u.arg); 562 toMakeUnreloadable.add(u.arg); 563 } else if (u.command.equals("delete")) { toEnable.remove(u.arg); 565 toDisable.remove(u.arg); toMakeReloadable.remove(u.arg); 567 toMakeUnreloadable.remove(u.arg); 568 toDelete.add(u.arg); 569 } else if (u.command.equals("create")) { toCreateReloable.remove(u.arg); 571 toCreate.add(u.arg); 572 } else if (u.command.equals("createReloadable")) { toCreate.remove(u.arg); 574 toCreateReloable.add(u.arg); 575 } else { 576 throw new IllegalStateException (); 577 } 578 } 579 doDelete(toDelete); 580 doDisable(toDisable, true); 581 it = toMakeReloadable.iterator(); 582 while (it.hasNext()) { 583 Module m = (Module)it.next(); 584 m.setReloadable(true); 585 } 586 it = toMakeUnreloadable.iterator(); 587 while (it.hasNext()) { 588 Module m = (Module)it.next(); 589 m.setReloadable(false); 590 } 591 doEnable(toEnable); 592 doCreate(toCreate, false); 593 doCreate(toCreateReloable, true); 594 } catch (RuntimeException re) { 595 Exceptions.printStackTrace(re); 596 ModuleBean[] _modules = modules; 599 if (_modules != null) { 600 for (int i = 0; i < _modules.length; i++) { 601 _modules[i].propertyChange(null); 602 } 603 } 604 } finally { 605 ModuleSelectionPanel.getGUI (false).setWaitingState (false, true); 606 } 607 SwingUtilities.invokeLater(AllModulesBean.this); 609 } 610 611 } 612 613 618 private void doDelete(Set modules) { 619 if (modules.isEmpty()) return; 620 err.log(Level.FINE, "doDelete: " + modules); 621 doDisable(modules, false); 623 Iterator it = modules.iterator(); 624 while (it.hasNext()) { 625 Module m = (Module)it.next(); 626 if (m.isFixed()) { 627 continue; 629 } 630 mgr.delete(m); 631 } 632 } 633 634 public int compare(Object o1, Object o2) { 635 Module m1 = (Module)o1; 636 Module m2 = (Module)o2; 637 int i = m1.getDisplayName().compareTo(m2.getDisplayName()); 638 if (i != 0) { 639 return i; 640 } else { 641 return m1.getCodeNameBase().compareTo(m2.getCodeNameBase()); 642 } 643 } 644 645 private void doDisable(Set modules, boolean cancelable) { 646 if (modules.isEmpty()) return; 647 err.log(Level.FINE, "doDisable: " + modules); 648 SortedSet realModules = new TreeSet(this); realModules.addAll(modules); 650 Iterator it = realModules.iterator(); 651 while (it.hasNext()) { 652 Module m = (Module)it.next(); 653 if (!m.isEnabled() || m.isAutoload() || m.isEager() || m.isFixed()) { 654 it.remove(); 656 } 657 } 658 List toDisable = mgr.simulateDisable(realModules); 659 it = toDisable.iterator(); 661 SortedSet others = new TreeSet(this); while (it.hasNext()) { 663 Module m = (Module)it.next(); 664 if (!m.isAutoload() && !m.isEager() && !realModules.contains(m)) { 665 others.add(m); 666 } 667 } 668 if (! others.isEmpty()) { 669 Component c = new ModuleEnableDisablePanel(false, realModules, others); 670 c.getAccessibleContext().setAccessibleName(NbBundle.getMessage(ModuleBean.class, "ACSN_TITLE_disabling")); 672 c.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(ModuleBean.class, "ACSD_TITLE_disabling")); 673 NotifyDescriptor d = new NotifyDescriptor.Confirmation(c, 674 NbBundle.getMessage(ModuleBean.class, "MB_TITLE_disabling"), 675 cancelable ? NotifyDescriptor.YES_NO_OPTION : NotifyDescriptor.DEFAULT_OPTION); 676 if (org.openide.DialogDisplayer.getDefault().notify(d) != NotifyDescriptor.YES_OPTION) { 677 ModuleBean[] _modules = this.modules; 680 if (_modules != null) { 681 for (int i = 0; i < _modules.length; i++) { 682 if (realModules.contains(_modules[i].module)) { 683 _modules[i].propertyChange(null); 684 } 685 } 686 } 687 return; 688 } 689 realModules.addAll(others); 690 } 691 mgr.disable(realModules); 693 } 694 695 private void doEnable(Set modules) { 696 if (modules.isEmpty()) return; 697 err.log(Level.FINE, "doEnable: " + modules); 698 SortedSet realModules = new TreeSet(this); realModules.addAll(modules); 700 Iterator it = realModules.iterator(); 701 while (it.hasNext()) { 702 Module m = (Module)it.next(); 703 if (m.isEnabled() || m.isAutoload() || m.isEager() || m.isFixed() || ! m.getProblems().isEmpty()) { 704 it.remove(); 706 } 707 } 708 List toEnable = mgr.simulateEnable(realModules); 709 it = toEnable.iterator(); 711 SortedSet others = new TreeSet(this); while (it.hasNext()) { 713 Module m = (Module)it.next(); 714 if (!m.isAutoload() && !m.isEager() && !realModules.contains(m)) { 715 others.add(m); 716 } 717 } 718 if (! others.isEmpty()) { 719 Component c = new ModuleEnableDisablePanel(true, realModules, others); 720 c.getAccessibleContext().setAccessibleName(NbBundle.getMessage(ModuleBean.class, "ACSN_TITLE_disabling")); 722 c.getAccessibleContext().setAccessibleDescription(NbBundle.getMessage(ModuleBean.class, "ACSD_TITLE_disabling")); 723 NotifyDescriptor d = new NotifyDescriptor.Confirmation(c, 724 NbBundle.getMessage(ModuleBean.class, "MB_TITLE_enabling"), 725 NotifyDescriptor.YES_NO_OPTION); 726 if (org.openide.DialogDisplayer.getDefault().notify(d) != NotifyDescriptor.YES_OPTION) { 727 ModuleBean[] _modules = this.modules; 730 if (_modules != null) { 731 for (int i = 0; i < _modules.length; i++) { 732 if (realModules.contains(_modules[i].module)) { 733 _modules[i].propertyChange(null); 734 } 735 } 736 } 737 return; 738 } 739 realModules.addAll(others); 740 } 741 it = toEnable.iterator(); 743 while (it.hasNext()) { 744 Module m = (Module)it.next(); 745 if (m.isReloadable()) { 746 try { 747 mgr.reload(m); 748 } catch (IOException ioe) { 749 Exceptions.printStackTrace(ioe); 750 ModuleBean[] _modules = this.modules; 752 if (_modules != null) { 753 for (int i = 0; i < _modules.length; i++) { 754 if (realModules.contains(_modules[i].module)) { 755 _modules[i].propertyChange(null); 756 } 757 } 758 } 759 return; 760 } 761 } 762 } 763 try { 764 mgr.enable(realModules); 765 } catch (InvalidException ie) { 766 err.log(Level.WARNING, null, ie); 767 Module bad = ie.getModule(); 768 if (bad == null) throw new IllegalStateException (); 769 ev.log(Events.FAILED_INSTALL_NEW_UNEXPECTED, new Object [] { bad, ie }); 770 ModuleBean[] _modules = this.modules; 772 if (_modules != null) { 773 for (int i = 0; i < _modules.length; i++) { 774 if (_modules[i].module == bad) { 775 _modules[i].propertyChange(null); 776 } 777 } 778 } 779 realModules.remove(ie.getModule()); 781 doEnable(realModules); 782 } 783 } 784 785 private void doCreate(Set files, boolean reloadable) { 786 if (files.isEmpty()) return; 787 err.log(Level.FINE, 788 "doCreate: " + files + " reloadable=" + reloadable); 789 Iterator it = files.iterator(); 790 while (it.hasNext()) { 791 File jar = (File )it.next(); 792 Module nue; 793 try { 794 nue = mgr.create(jar, new ModuleHistory(jar.getAbsolutePath()), reloadable, false, false); 795 } catch (IOException ioe) { 796 DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Exception(ioe)); 797 continue; 798 } catch (DuplicateException dupe) { 799 Module old = dupe.getOldModule(); 801 if (old.isFixed()) { 802 continue; 804 } 805 if (old.isEnabled()) { 806 if (old.isAutoload() || old.isEager()) { 808 continue; 810 } 811 doDisable(Collections.singleton(old), true); 812 if (old.isEnabled()) { 813 continue; 815 } 816 } 817 mgr.delete(old); 818 try { 819 nue = mgr.create(jar, new ModuleHistory(jar.getAbsolutePath()), reloadable, false, false); 820 } catch (IOException ioe) { 821 DialogDisplayer.getDefault().notifyLater(new NotifyDescriptor.Exception(ioe)); 822 continue; 823 } catch (DuplicateException dupe2) { 824 Exceptions.printStackTrace(dupe2); 826 continue; 827 } 828 } 829 if (nue.getProblems().isEmpty()) { 831 doEnable(Collections.singleton(nue)); 832 } else { 835 ev.log(Events.FAILED_INSTALL_NEW, new Object [] { Collections.singleton(nue) }); 837 } 838 } 839 } 840 841 847 850 public static final int RELATION_DIRECTLY_NEEDS = 0; 851 854 public static final int RELATION_TRANSITIVELY_NEEDS = 1; 855 858 public static final int RELATION_DIRECTLY_NEEDED_BY = 2; 859 862 public static final int RELATION_TRANSITIVELY_NEEDED_BY = 3; 863 864 867 public interface RelationCallback { 868 871 void result(Set<ModuleBean> modules); 872 } 873 874 private static final RequestProcessor RELATION_COMPUTER_RP = new RequestProcessor("RelationComputer"); 890 public void getRelations(ModuleBean mb, int type, RelationCallback callback) { 891 if (type != RELATION_DIRECTLY_NEEDS && type != RELATION_TRANSITIVELY_NEEDS && 892 type != RELATION_DIRECTLY_NEEDED_BY && type != RELATION_TRANSITIVELY_NEEDED_BY) { 893 throw new IllegalArgumentException ("bad type: " + type); } 895 RELATION_COMPUTER_RP.post(new RelationComputer(mb.module, type, callback)); 896 } 897 898 private class RelationComputer implements Runnable { 899 private int stage; 900 private final Module m; 901 private final int type; 902 private final RelationCallback callback; 903 private Set result; public RelationComputer(Module m, int type, RelationCallback callback) { 905 this.stage = 0; 906 this.m = m; 907 this.type = type; 908 this.callback = callback; 909 } 910 public void run() { 911 switch (stage) { 912 case 0: 913 stage = 1; 914 mgr.mutex().readAccess(this); 915 break; 916 case 1: 917 compute(); 918 stage = 2; 919 SwingUtilities.invokeLater(this); 920 break; 921 default: 922 Set mbresult = new HashSet(result.size() * 2 + 1); ModuleBean[] _modules = getModules(); 925 for (int i = 0; i < _modules.length; i++) { 926 if (result.contains(_modules[i].module)) { 927 mbresult.add(_modules[i]); 928 } 929 } 930 callback.result(mbresult); 931 break; 932 } 933 } 934 937 private void compute() { 938 switch (type) { 939 case RELATION_DIRECTLY_NEEDS: 940 result = mgr.getModuleInterdependencies(m, false, false); 941 break; 942 case RELATION_DIRECTLY_NEEDED_BY: 943 result = mgr.getModuleInterdependencies(m, true, false); 944 break; 945 case RELATION_TRANSITIVELY_NEEDS: 946 result = mgr.getModuleInterdependencies(m, false, true); 947 break; 948 case RELATION_TRANSITIVELY_NEEDED_BY: 949 result = mgr.getModuleInterdependencies(m, true, true); 950 break; 951 default: 952 assert false : type; 953 } 954 } 955 } 956 957 } 958 959 960 private static final class Update { 961 public final String command; 962 public final Object arg; 963 public Update(String command, Object arg) { 964 this.command = command; 965 this.arg = arg; 966 } 967 public boolean equals(Object o) { 968 if (! (o instanceof Update)) return false; 969 Update u = (Update)o; 970 return command.equals(u.command) && arg.equals(u.arg); 971 } 972 public int hashCode() { 973 return command.hashCode() ^ arg.hashCode(); 974 } 975 public String toString() { 976 return "Update[" + command + "," + arg + "]"; } 978 } 979 980 } 981 | Popular Tags |