1 19 20 package org.netbeans.core.startup; 21 22 import java.io.BufferedInputStream ; 23 import java.io.BufferedOutputStream ; 24 import java.io.ByteArrayInputStream ; 25 import java.io.ByteArrayOutputStream ; 26 import java.io.File ; 27 import java.io.FileInputStream ; 28 import java.io.FileOutputStream ; 29 import java.io.IOException ; 30 import java.io.InputStream ; 31 import java.io.OutputStream ; 32 import java.net.URL ; 33 import java.util.ArrayList ; 34 import java.util.Collections ; 35 import java.util.Date ; 36 import java.util.HashMap ; 37 import java.util.HashSet ; 38 import java.util.List ; 39 import java.util.Locale ; 40 import java.util.Map ; 41 import java.util.Set ; 42 import java.util.StringTokenizer ; 43 import java.util.jar.Attributes ; 44 import java.util.jar.JarEntry ; 45 import java.util.jar.JarFile ; 46 import java.util.jar.Manifest ; 47 import java.util.logging.Level ; 48 import org.netbeans.Events; 49 import org.netbeans.InvalidException; 50 import org.netbeans.Module; 51 import org.netbeans.ModuleInstaller; 52 import org.netbeans.ModuleManager; 53 import org.netbeans.Util; 54 import org.netbeans.core.startup.layers.ModuleLayeredFileSystem; 55 import org.openide.filesystems.FileObject; 56 import org.openide.filesystems.FileStateInvalidException; 57 import org.openide.filesystems.FileUtil; 58 import org.openide.filesystems.Repository; 59 import org.openide.modules.Dependency; 60 import org.openide.modules.ModuleInstall; 61 import org.openide.modules.SpecificationVersion; 62 import org.openide.util.Exceptions; 63 import org.openide.util.NbCollections; 64 import org.openide.util.SharedClassObject; 65 import org.openide.util.NbBundle; 66 import org.openide.util.lookup.InstanceContent; 67 import org.xml.sax.SAXException ; 68 69 76 final class NbInstaller extends ModuleInstaller { 77 78 79 private final Map <Module,Set <ManifestSection>> sections = new HashMap <Module,Set <ManifestSection>>(100); 80 81 private final Map <Module,Class <? extends ModuleInstall>> installs = new HashMap <Module,Class <? extends ModuleInstall>>(100); 82 83 private final Map <Module,String > layers = new HashMap <Module,String >(100); 84 85 private boolean initializedFolderLookup = false; 86 87 private final Events ev; 88 89 private ModuleList moduleList; 90 91 private ModuleManager mgr; 92 93 private final Map <Module,Set <String >> kosherPackages = new HashMap <Module,Set <String >>(100); 94 95 private static String [] specialResourcePrefixes = null; 96 97 102 public NbInstaller(Events ev) { 103 this.ev = ev; 104 } 105 106 107 void registerList(ModuleList list) { 108 if (moduleList != null) throw new IllegalStateException (); 109 moduleList = list; 110 } 111 void registerManager(ModuleManager manager) { 112 if (mgr != null) throw new IllegalStateException (); 113 mgr = manager; 114 } 115 116 public void prepare(Module m) throws InvalidException { 118 ev.log(Events.PREPARE, m); 119 Set <ManifestSection> mysections = null; 120 Class <?> clazz = null; 121 { 122 for (Map.Entry <String ,Attributes > entry : m.getManifest().getEntries().entrySet()) { 124 ManifestSection section = ManifestSection.create(entry.getKey(), entry.getValue(), m); 125 if (section != null) { 126 if (mysections == null) { 127 mysections = new HashSet <ManifestSection>(25); 128 } 129 mysections.add(section); 130 } 131 } 132 } 133 String installClass = m.getManifest().getMainAttributes().getValue("OpenIDE-Module-Install"); if (installClass != null) { 135 String installClassName; 136 try { 137 installClassName = Util.createPackageName(installClass); 138 } catch (IllegalArgumentException iae) { 139 InvalidException ie = new InvalidException(m, iae.toString()); 140 ie.initCause(iae); 141 throw ie; 142 } 143 if (installClass.endsWith(".ser")) throw new InvalidException(m, "Serialized module installs not supported: " + installClass); try { 145 clazz = Class.forName(installClassName, false, m.getClassLoader()); 154 if (clazz.getClassLoader() != m.getClassLoader()) { 155 ev.log(Events.WRONG_CLASS_LOADER, m, clazz, m.getClassLoader()); 156 } 157 Class <?> c; 159 for (c = clazz; c != ModuleInstall.class && c != Object .class; c = c.getSuperclass()) { 160 try { 161 c.getDeclaredMethod("validate"); ModuleInstall install = SharedClassObject.findObject(clazz.asSubclass(ModuleInstall.class), true); 166 install.validate(); 169 } catch (NoSuchMethodException nsme) { 170 } 172 } 173 if (c == Object .class) throw new ClassCastException ("Should extend ModuleInstall: " + clazz.getName()); } catch (Exception t) { 176 InvalidException ie = new InvalidException(m, t.toString()); 177 ie.initCause(t); 178 throw ie; 179 } catch (LinkageError t) { 180 InvalidException ie = new InvalidException(m, t.toString()); 181 ie.initCause(t); 182 throw ie; 183 } 184 } 185 String layerResource = m.getManifest().getMainAttributes().getValue("OpenIDE-Module-Layer"); if (layerResource != null) { 189 URL layer = m.getClassLoader().getResource(layerResource); 190 if (layer == null) throw new InvalidException(m, "Layer not found: " + layerResource); } 192 String helpSetName = m.getManifest().getMainAttributes().getValue("OpenIDE-Module-Description"); if (helpSetName != null) { 194 Util.err.warning("Use of OpenIDE-Module-Description in " + m.getCodeNameBase() + " is deprecated."); 195 Util.err.warning("(Please install help using an XML layer instead.)"); 196 } 197 if (mysections != null) { 199 sections.put(m, mysections); 200 } 201 if (clazz != null) { 202 installs.put(m, clazz.asSubclass(ModuleInstall.class)); 203 } 204 if (layerResource != null) { 205 layers.put(m, layerResource); 206 } 207 } 208 209 public void dispose(Module m) { 210 Util.err.fine("dispose: " + m); 211 Set <ManifestSection> s = sections.remove(m); 213 if (s != null) { 214 for (ManifestSection sect : s) { 215 sect.dispose(); 216 } 217 } 218 installs.remove(m); 219 layers.remove(m); 220 kosherPackages.remove(m); 221 } 222 223 public void load(List <Module> modules) { 224 ev.log(Events.START_LOAD, modules); 225 226 if (mgr != null) { MainLookup.systemClassLoaderChanged(mgr.getClassLoader()); 230 } 231 ev.log(Events.PERF_TICK, "META-INF/services/ additions registered"); 233 for (Module m: modules) { 234 checkForDeprecations(m); 235 openideModuleEnabled(m); 236 } 237 238 loadLayers(modules, true); 239 ev.log(Events.PERF_TICK, "layers loaded"); 241 ev.log(Events.PERF_START, "NbInstaller.load - sections"); ev.log(Events.LOAD_SECTION); 243 CoreBridge.conditionallyLoaderPoolTransaction(true); 244 try { 245 for (Module m: modules) { 246 try { 247 loadSections(m, true); 248 } catch (Exception t) { 249 Util.err.log(Level.SEVERE, null, t); 250 } catch (LinkageError le) { 251 Util.err.log(Level.SEVERE, null, le); 252 } 253 ev.log(Events.PERF_TICK, "sections for " + m.getCodeName() + " loaded"); } 255 } finally { 256 CoreBridge.conditionallyLoaderPoolTransaction(false); 257 } 258 ev.log(Events.PERF_END, "NbInstaller.load - sections"); 260 if (! initializedFolderLookup) { 262 Util.err.fine("modulesClassPathInitialized"); 263 MainLookup.modulesClassPathInitialized(); 264 initializedFolderLookup = true; 265 } 266 267 Main.initUICustomizations(); 269 270 ev.log(Events.PERF_START, "NbInstaller.load - ModuleInstalls"); for (Module m: modules) { 272 try { 273 loadCode(m, true); 274 } catch (Exception t) { 275 Util.err.log(Level.SEVERE, null, t); 276 } catch (LinkageError le) { 277 Util.err.log(Level.SEVERE, null, le); 278 } catch (AssertionError e) { 279 Util.err.log(Level.SEVERE, null, e); 280 } 281 ev.log(Events.PERF_TICK, "ModuleInstall for " + m.getCodeName() + " called"); } 283 ev.log(Events.PERF_END, "NbInstaller.load - ModuleInstalls"); 285 ev.log(Events.FINISH_LOAD, modules); 286 287 maybeSaveManifestCache(); 288 289 if (Boolean.getBoolean("netbeans.preresolve.classes")) { 290 preresolveClasses(modules); 291 } 292 } 293 294 public void unload(List <Module> modules) { 295 ev.log(Events.START_UNLOAD, modules); 296 for (Module m: modules) { 297 try { 298 loadCode(m, false); 299 } catch (Exception t) { 300 Util.err.log(Level.SEVERE, null, t); 301 } catch (LinkageError le) { 302 Util.err.log(Level.SEVERE, null, le); 303 } 304 } 305 CoreBridge.conditionallyLoaderPoolTransaction(true); 306 try { 307 for (Module m: modules) { 308 try { 309 loadSections(m, false); 310 } catch (Exception t) { 311 Util.err.log(Level.SEVERE, null, t); 312 } catch (LinkageError le) { 313 Util.err.log(Level.SEVERE, null, le); 314 } 315 } 316 } finally { 317 try { 318 CoreBridge.conditionallyLoaderPoolTransaction(false); 319 } catch (RuntimeException e) { 320 Util.err.log(Level.SEVERE, null, e); 321 } 322 } 323 loadLayers(modules, false); 324 ev.log(Events.FINISH_UNLOAD, modules); 325 } 326 327 328 @SuppressWarnings ("deprecation") private void loadCode(Module m, boolean load) throws Exception { 330 Class <? extends ModuleInstall> instClazz = installs.get(m); 331 if (instClazz != null) { 332 ModuleInstall inst = SharedClassObject.findObject(instClazz, true); 333 if (load) { 334 if (moduleList != null) { 335 moduleList.installPrepare(m, inst); 336 } 337 Object history = m.getHistory(); 339 if (history instanceof ModuleHistory) { 340 ModuleHistory h = (ModuleHistory)history; 341 if (h.isPreviouslyInstalled()) { 342 SpecificationVersion oldSpec = h.getOldSpecificationVersion(); 344 SpecificationVersion nueSpec = m.getSpecificationVersion(); 345 if (m.getCodeNameRelease() != h.getOldMajorVersion() || 346 (oldSpec == null ^ nueSpec == null) || 347 (oldSpec != null && nueSpec != null && oldSpec.compareTo(nueSpec) != 0)) { 348 ev.log(Events.UPDATE, m); 350 inst.updated(h.getOldMajorVersion(), oldSpec == null ? null : oldSpec.toString()); 351 } else { 352 ev.log(Events.RESTORE, m); 354 inst.restored(); 355 } 356 } else { 357 ev.log(Events.INSTALL, m); 359 inst.installed(); 360 } 361 } else { 362 ev.log(Events.RESTORE, m); 364 inst.restored(); 365 } 366 if (moduleList != null) { 367 moduleList.installPostpare(m, inst); 368 } 369 } else { 370 ev.log(Events.UNINSTALL, m); 371 inst.uninstalled(); 372 if (m.getHistory() instanceof ModuleHistory) { 373 ((ModuleHistory)m.getHistory()).resetHistory(); 374 } 375 } 376 } 377 } 378 379 380 @SuppressWarnings ("deprecation") private void loadSections(Module m, boolean load) throws Exception { 382 Set <ManifestSection> s = sections.get(m); 383 if (s == null) { 384 return; 385 } 386 boolean attachedToMA = false; 388 try { 389 ev.log(Events.LOAD_SECTION); 390 for (ManifestSection sect : s) { 391 if (sect instanceof ManifestSection.ActionSection) { 392 if (! attachedToMA) { 393 Object category = m.getLocalizedAttribute("OpenIDE-Module-Display-Category"); if (category == null) { 396 category = m.getCodeNameBase(); 398 } 399 CoreBridge.getDefault().attachToCategory(category); 400 attachedToMA = true; 401 } 402 CoreBridge.getDefault ().loadActionSection((ManifestSection.ActionSection)sect, load); 403 } else if (sect instanceof ManifestSection.ClipboardConvertorSection) { 404 loadGenericSection(sect, load); 405 } else if (sect instanceof ManifestSection.DebuggerSection) { 406 loadGenericSection(sect, load); 407 } else if (sect instanceof ManifestSection.LoaderSection) { 408 CoreBridge.getDefault().loadLoaderSection((ManifestSection.LoaderSection)sect, load); 409 } else { 410 assert false : sect; 411 } 412 } 413 } finally { 414 if (attachedToMA) { 415 CoreBridge.getDefault ().attachToCategory (null); 416 } 417 } 418 } 419 420 422 427 private void loadGenericSection(ManifestSection s, boolean load) { 428 CoreBridge.getDefault().loadDefaultSection(s, convertor, load); 429 } 430 431 private final InstanceContent.Convertor<ManifestSection,Object > convertor = new Convertor(); 432 private final class Convertor implements InstanceContent.Convertor<ManifestSection,Object > { Convertor() {} 434 public Object convert(ManifestSection s) { 435 try { 436 return s.getInstance(); 437 } catch (Exception e) { 438 Util.err.log(Level.WARNING, null, e); 439 loadGenericSection(s, false); 444 return null; 445 } 446 } 447 public Class <?> type(ManifestSection s) { 448 return s.getSuperclass(); 449 } 450 451 455 public String id(ManifestSection obj) { 456 return obj.toString (); 457 } 458 459 463 public String displayName(ManifestSection obj) { 464 return obj.toString (); 465 } 466 467 } 468 469 474 private void loadLayers(List <Module> modules, boolean load) { 475 ev.log(load ? Events.LOAD_LAYERS : Events.UNLOAD_LAYERS, modules); 476 modules = new ArrayList <Module>(modules); 478 Collections.reverse(modules); 479 Map <ModuleLayeredFileSystem,List <URL >> urls = new HashMap <ModuleLayeredFileSystem,List <URL >>(5); 480 for (Module m: modules) { 481 String s = layers.get(m); 482 if (s != null) { 483 Util.err.fine("loadLayer: " + s + " load=" + load); 484 String base, ext; 486 int idx = s.lastIndexOf('.'); if (idx == -1) { 488 base = s; 489 ext = ""; } else { 491 base = s.substring(0, idx); 492 ext = s.substring(idx); 493 } 494 ClassLoader cl = m.getClassLoader(); 495 ModuleLayeredFileSystem host; 496 if (m.isReloadable()) { 501 host = ModuleLayeredFileSystem.getUserModuleLayer(); 502 } else { 503 host = ModuleLayeredFileSystem.getInstallationModuleLayer(); 504 } 505 List <URL > theseurls = urls.get(host); 506 if (theseurls == null) { 507 theseurls = new ArrayList <URL >(100); 508 urls.put(host, theseurls); 509 } 510 boolean foundSomething = false; 511 for (String suffix : NbCollections.iterable(NbBundle.getLocalizingSuffixes())) { 512 String resource = base + suffix + ext; 513 URL u = cl.getResource(resource); 514 if (u != null) { 515 theseurls.add(u); 516 foundSomething = true; 517 } 518 } 519 if (! foundSomething) { 520 Util.err.fine("Module layer not found: " + s); 522 continue; 523 } 524 } 525 } 526 for (Map.Entry <ModuleLayeredFileSystem,List <URL >> entry: urls.entrySet()) { 528 ModuleLayeredFileSystem host = entry.getKey(); 529 List <URL > theseurls = entry.getValue(); 530 Util.err.fine("Adding/removing layer URLs: host=" + host + " urls=" + theseurls); 531 try { 532 if (load) { 533 host.addURLs(theseurls); 534 } else { 535 host.removeURLs(theseurls); 536 } 537 } catch (Exception e) { 538 Util.err.log(Level.WARNING, null, e); 539 } 540 } 541 } 542 543 550 private void checkForDeprecations(Module m) { 551 if (!Boolean.valueOf((String )m.getAttribute("OpenIDE-Module-Deprecated")).booleanValue()) { for (Dependency dep : m.getDependencies()) { 553 if (dep.getType() == Dependency.TYPE_MODULE) { 554 String cnb = (String ) Util.parseCodeName(dep.getName())[0]; 555 Module o = mgr.get(cnb); 556 if (o == null) throw new IllegalStateException ("No such module: " + cnb); if (Boolean.parseBoolean((String ) o.getAttribute("OpenIDE-Module-Deprecated"))) { String message = (String )o.getLocalizedAttribute("OpenIDE-Module-Deprecation-Message"); if (message != null) { 563 Util.err.warning("the module " + m.getCodeNameBase() + " uses " + cnb + " which is deprecated: " + message); } else { 565 Util.err.warning("the module " + m.getCodeNameBase() + " uses " + cnb + " which is deprecated."); } 567 } 568 } 569 } 570 } 571 } 572 573 public boolean closing(List <Module> modules) { 574 Util.err.fine("closing: " + modules); 575 for (Module m: modules) { 576 Class <? extends ModuleInstall> instClazz = installs.get(m); 577 if (instClazz != null) { 578 try { 579 ModuleInstall inst = SharedClassObject.findObject(instClazz, true); 580 if (! inst.closing()) { 581 Util.err.fine("Module " + m + " refused to close"); 582 return false; 583 } 584 } catch (RuntimeException re) { 585 Util.err.log(Level.SEVERE, null, re); 586 } catch (LinkageError le) { 588 Util.err.log(Level.SEVERE, null, le); 589 } 590 } 591 } 592 return true; 593 } 594 595 public void close(List <Module> modules) { 596 Util.err.fine("close: " + modules); 597 ev.log(Events.CLOSE); 598 for (Module m : modules) { 603 Class <? extends ModuleInstall> instClazz = installs.get(m); 604 if (instClazz != null) { 605 try { 606 ModuleInstall inst = SharedClassObject.findObject(instClazz, true); 607 if (inst == null) throw new IllegalStateException ("Inconsistent state: " + instClazz); inst.close(); 609 } catch (ThreadDeath td) { 610 throw td; 611 } catch (Throwable t) { 612 Util.err.log(Level.SEVERE, null, t); 614 } 616 } 617 } 618 } 619 620 private AutomaticDependencies autoDepsHandler = null; 621 622 629 public void refineDependencies(Module m, Set <Dependency> dependencies) { 630 637 if (Boolean.getBoolean("org.netbeans.core.modules.NbInstaller.noAutoDeps")) { 638 return; 640 } 641 if (autoDepsHandler == null) { 642 FileObject depsFolder = Repository.getDefault().getDefaultFileSystem().findResource("ModuleAutoDeps"); 643 if (depsFolder != null) { 644 FileObject[] kids = depsFolder.getChildren(); 645 List <URL > urls = new ArrayList <URL >(Math.max(kids.length, 1)); 646 for (FileObject kid : kids) { 647 if (kid.hasExt("xml")) { try { 649 urls.add(kid.getURL()); 650 } catch (FileStateInvalidException e) { 651 Util.err.log(Level.WARNING, null, e); 652 } 653 } 654 } 655 try { 656 autoDepsHandler = AutomaticDependencies.parse(urls.toArray(new URL [urls.size()])); 657 } catch (IOException e) { 658 Util.err.log(Level.WARNING, null, e); 659 } catch (SAXException e) { 660 Util.err.log(Level.WARNING, null, e); 661 } 662 } 663 if (autoDepsHandler == null) { 664 autoDepsHandler = AutomaticDependencies.empty(); 666 } 667 if (Util.err.isLoggable(Level.FINE)) { 668 Util.err.fine("Auto deps: " + autoDepsHandler); 669 } 670 } 671 AutomaticDependencies.Report rep = autoDepsHandler.refineDependenciesAndReport(m.getCodeNameBase(), dependencies); 672 if (rep.isModified()) { 673 Util.err.warning("had to upgrade dependencies for module " + m.getCodeNameBase() + ": added = " + rep.getAdded() + " removed = " + rep.getRemoved() + "; details: " + rep.getMessages()); 674 } 675 } 676 677 public String [] refineProvides (Module m) { 678 if (m.getCodeNameBase ().equals ("org.openide.modules")) { List <String > arr = new ArrayList <String >(4); 680 681 boolean isOS2 = (org.openide.util.Utilities.getOperatingSystem () & org.openide.util.Utilities.OS_OS2) != 0; 682 683 if (org.openide.util.Utilities.isUnix ()) { 684 arr.add ("org.openide.modules.os.Unix"); if (!org.openide.util.Utilities.isMac()) { 686 arr.add("org.openide.modules.os.PlainUnix"); } 688 } 689 690 if ( 691 org.openide.util.Utilities.isWindows () 692 ) { 693 arr.add ("org.openide.modules.os.Windows"); } 695 696 if (org.openide.util.Utilities.isMac()) { 697 arr.add ("org.openide.modules.os.MacOSX"); } 699 if (isOS2) { 700 arr.add ("org.openide.modules.os.OS2"); } 702 703 arr.add ("org.openide.modules.ModuleFormat1"); 706 return arr.toArray (new String [0]); 707 } 708 return null; 709 } 710 711 public boolean shouldDelegateResource(Module m, Module parent, String pkg) { 712 if (parent == null) { 715 for (String cppkg : CLASSPATH_PACKAGES) { 717 if (pkg.startsWith(cppkg) && !findKosher(m).contains(cppkg)) { 718 if (Util.err.isLoggable(Level.FINE)) { 720 Util.err.fine("Refusing to load classpath package " + pkg + " for " + m.getCodeNameBase() + " without a proper dependency"); } 722 return false; 723 } 724 } 725 } 726 return true; 727 } 728 729 private static final String [] CLASSPATH_PACKAGES = new String [] { 730 "org/netbeans/core/startup/", 732 "com/sun/tools/javac/", 734 "com/sun/tools/javadoc/", 735 "com/sun/javadoc/", 736 "com/sun/source/", 737 "javax/annotation/", 738 "javax/lang/model/", 739 "javax/tools/", 740 "javax/xml/bind/", "javax/xml/ws/", "javax/xml/stream/", "javax/jws/", "javax/xml/soap/" }; 747 748 private Set <String > findKosher(Module m) { 749 Set <String > s = kosherPackages.get(m); 750 if (s == null) { 751 s = new HashSet <String >(); 752 Set <Dependency> deps = m.getDependencies(); 753 SpecificationVersion openide = Util.getModuleDep(deps, "org.openide"); boolean pre27853 = (openide == null || openide.compareTo(new SpecificationVersion("1.3.12")) < 0); for (Dependency dep : deps) { 756 if (dep.getType() == Dependency.TYPE_MODULE && 758 dep.getName().equals("org.netbeans.core.startup/1")) { s.add("org/netbeans/core/startup/"); } else if (pre27853 && dep.getType() == Dependency.TYPE_MODULE) { 762 String name = dep.getName(); 766 int idx = name.indexOf('/'); 767 if (idx != -1) { 768 name = name.substring(0, idx); 769 } 770 Module other = mgr.get(name); 771 if (other == null) throw new IllegalStateException ("Should have found dep " + dep + " from " + m); s.addAll(findKosher(other)); 773 } else if (dep.getType() == Dependency.TYPE_PACKAGE) { 774 String depname = dep.getName(); 775 String req; 776 int idx = depname.indexOf('['); if (idx == -1) { 778 req = depname.replace('.', '/').concat("/"); } else if (idx == 0) { 782 int idx2 = depname.lastIndexOf('.'); 785 req = depname.substring(1, idx2).replace('.', '/').concat("/"); } else { 787 req = depname.substring(0, idx).replace('.', '/').concat("/"); } 791 for (String cppkg : CLASSPATH_PACKAGES) { 792 if (req.startsWith(cppkg)) { 793 s.add(cppkg); 796 } 797 } 798 } 799 } 800 if (s.isEmpty()) s = Collections.<String >emptySet(); 801 kosherPackages.put(m, s); 802 } 803 return s; 804 } 805 806 808 private static boolean withoutOptimizations; 809 812 static void openideModuleEnabled(Module module) { 813 String m = module.getCodeNameBase(); 814 if (!m.startsWith("org.openide.")) { 815 return; 816 } 817 818 if ("org.openide.util".equals(m)) return; if ("org.openide.actions".equals(m)) return; if ("org.openide.awt".equals(m)) return; if ("org.openide.modules".equals(m)) return; if ("org.openide.nodes".equals(m)) return; if ("org.openide.windows".equals(m)) return; if ("org.openide.explorer".equals(m)) return; if ("org.openide.util.enumerations".equals(m)) return; if ("org.openide.execution".equals(m)) return; if ("org.openide.options".equals(m)) return; if ("org.openide.execution".equals(m)) return; if ("org.openide.loaders".equals(m)) return; if ("org.openide.dialogs".equals(m)) return; if ("org.openide.filesystems".equals(m)) return; if ("org.openide.io".equals(m)) return; if ("org.openide.text".equals(m)) return; if ("org.openide.src".equals(m)) return; 836 Util.err.warning("Disabling openide load optimizations due to use of " + m); 838 withoutOptimizations = true; 839 } 840 841 856 private static final String [][] CLASSPATH_JARS = { 857 {"core", "org/netbeans/core/", "org/netbeans/beaninfo/"}, {"boot"}, }; 861 862 865 public boolean isSpecialResource(String pkg) { 866 873 if (pkg.startsWith("org/openide/")) { 875 876 if ("org/openide/".equals (pkg)) return true; if ("org/openide/actions/".equals (pkg)) return true; if ("org/openide/awt/".equals (pkg)) return true; if ("org/openide/cookies/".equals (pkg)) return true; 885 if ("org/openide/explorer/propertysheet/editors/".equals (pkg)) return true; 888 if ("org/openide/windows/".equals (pkg)) return true; 891 if ("org/openide/text/".equals (pkg)) return true; 894 if ("org/openide/util/actions/".equals (pkg)) return true; 897 if (withoutOptimizations) { 898 if ("org/openide/explorer/".equals (pkg)) return true; if ("org/openide/util/".equals (pkg)) return true; } 902 } 903 904 if (isSpecialResourceFromSystemProperty(pkg)) { 905 return true; 906 } 907 908 if (pkg.equals("org/w3c/dom/")) return true; if (pkg.equals("org/w3c/dom/ls/")) return true; return super.isSpecialResource(pkg); 913 } 914 915 920 private boolean isSpecialResourceFromSystemProperty(String pkg) { 921 for (String prefix : getSpecialResourcePrefixes()) { 922 if (pkg.startsWith(prefix)) { 923 return true; 924 } 925 } 926 return false; 927 } 928 929 934 private static String [] getSpecialResourcePrefixes() { 935 if (specialResourcePrefixes == null) { 936 String sysProp = System.getProperty("org.netbeans.core.startup.specialResource"); 937 if (sysProp != null) { 938 specialResourcePrefixes = sysProp.split(","); 939 } else { 940 specialResourcePrefixes = new String [0]; 941 } 942 } 943 return specialResourcePrefixes; 944 } 945 946 953 String getEffectiveClasspath(Module m) { 954 if (!m.isEnabled()) { 955 return ""; } 958 List <String > l = new ArrayList <String >(100); 960 createBootClassPath(l); 962 Set <String > kosher = m.isFixed() ? null : findKosher(m); 965 StringTokenizer tok = new StringTokenizer (System.getProperty("java.class.path", ""), File.pathSeparator); 966 while (tok.hasMoreTokens()) { 967 addStartupClasspathEntry(new File (tok.nextToken()), l, kosher); 968 } 969 tok = new StringTokenizer (System.getProperty("netbeans.dynamic.classpath", ""), File.pathSeparator); 971 while (tok.hasMoreTokens()) { 972 addStartupClasspathEntry(new File (tok.nextToken()), l, kosher); 973 } 974 Set <Module> modulesConsidered = new HashSet <Module>(50); 977 Set <String > implDeps = new HashSet <String >(10); 980 for (Dependency dep : m.getDependencies()) { 981 if (dep.getType() == Dependency.TYPE_MODULE && dep.getComparison() == Dependency.COMPARE_IMPL) { 983 implDeps.add(dep.getName()); 986 } 987 } 988 SpecificationVersion openide = Util.getModuleDep(m.getDependencies(), "org.openide"); boolean pre27853 = (openide == null || openide.compareTo(new SpecificationVersion("1.3.12")) < 0); addModuleClasspathEntries(m, m, modulesConsidered, implDeps, l, pre27853 ? Integer.MAX_VALUE : 1); 992 StringBuilder buf = new StringBuilder (l.size() * 100 + 1); 994 for (String s: l) { 995 if (buf.length() > 0) { 996 buf.append(File.pathSeparatorChar); 997 } 998 buf.append(s); 999 } 1000 return buf.toString(); 1001 } 1002 1003 private static void createBootClassPath(List <String > l) { 1005 String boot = System.getProperty("sun.boot.class.path"); if (boot != null) { 1008 StringTokenizer tok = new StringTokenizer (boot, File.pathSeparator); 1009 while (tok.hasMoreTokens()) { 1010 l.add(tok.nextToken()); 1011 } 1012 } 1013 1014 String extensions = System.getProperty("java.ext.dirs"); if (extensions != null) { 1017 for (StringTokenizer st = new StringTokenizer (extensions, File.pathSeparator); st.hasMoreTokens();) { 1018 File dir = new File (st.nextToken()); 1019 File [] entries = dir.listFiles(); 1020 if (entries != null) { 1021 for (File f : entries) { 1022 String name = f.getName().toLowerCase(Locale.US); 1023 if (name.endsWith(".zip") || name.endsWith(".jar")) { l.add(f.getAbsolutePath()); 1025 } 1026 } 1027 } 1028 } 1029 } 1030 } 1031 1032 1038 private static void addStartupClasspathEntry(File cpEntry, List <String > cp, Set <String > kosher) { 1039 if (cpEntry.isDirectory()) { 1040 cp.add(cpEntry.getAbsolutePath()); 1041 return; 1042 } 1043 String name = cpEntry.getName(); 1045 for (String [] cpjar : CLASSPATH_JARS) { 1046 if (kosher != null && name.startsWith(cpjar[0])) { 1047 StringBuffer entry = null; for (int k = 1; k < cpjar.length; k++) { 1050 String pkg = cpjar[k]; 1051 if (kosher.contains(pkg)) { 1052 if (entry == null) { 1054 entry = new StringBuffer (100); 1055 entry.append(cpEntry.getAbsolutePath()); 1056 entry.append('['); } else { 1058 entry.append(','); } 1060 entry.append(pkg.replace('/', '.')); entry.append("**"); } 1064 } 1065 if (entry != null) { 1066 entry.append(']'); cp.add(entry.toString()); 1069 } 1070 return; 1071 } 1072 } 1073 cp.add(cpEntry.getAbsolutePath()); 1075 } 1076 1077 1086 private void addModuleClasspathEntries(Module m, Module orig, Set <Module> considered, Set <String > implDeps, List <String > cp, int depth) { 1087 if (!considered.add(m)) return; 1089 for (Dependency dep : m.getDependencies()) { 1090 if (dep.getType() == Dependency.TYPE_MODULE) { 1091 String cnb = (String ) Util.parseCodeName(dep.getName())[0]; 1092 Module next = mgr.get(cnb); 1093 if (next == null) throw new IllegalStateException ("No such module: " + cnb); if (depth > 0) { 1095 addModuleClasspathEntries(next, orig, considered, implDeps, cp, depth - 1); 1096 } 1097 } 1098 } 1099 boolean friend = (m == orig) || implDeps.contains(m.getCodeName()); 1103 Module.PackageExport[] exports = friend ? null : m.getPublicPackages(); 1106 String qualification = ""; if (exports != null) { 1108 if (exports.length == 0) { 1109 return; 1111 } 1112 StringBuffer b = new StringBuffer (100); 1114 b.append('['); for (int i = 0; i < exports.length; i++) { 1116 if (i > 0) { 1117 b.append(','); } 1119 b.append(exports[i].pkg.replace('/', '.')); b.append(exports[i].recursive ? "**" : "*"); } 1122 b.append(']'); qualification = b.toString(); 1124 } 1125 for (File jar : m.getAllJars()) { 1126 cp.add(jar.getAbsolutePath() + qualification); 1127 } 1128 } 1129 1130 1132 1143 private File manifestCacheFile; 1144 1145 1151 private boolean usingManifestCache; 1152 1153 { 1154 usingManifestCache = Boolean.valueOf(System.getProperty("netbeans.cache.manifests", "true")).booleanValue(); 1155 if (usingManifestCache) { 1156 String userdir = System.getProperty("netbeans.user"); 1157 if (userdir != null) { 1158 manifestCacheFile = new File (new File (new File (new File (userdir), "var"), "cache"), "all-manifests.dat"); Util.err.fine("Using manifest cache in " + manifestCacheFile); 1160 } else { 1161 usingManifestCache = false; 1163 Util.err.fine("Not using any manifest cache; no user directory"); 1164 } 1165 } else { 1166 Util.err.fine("Manifest cache disabled"); 1167 } 1168 } 1169 1170 1175 private Map <File ,Object []> manifestCache = null; 1176 1177 1182 private boolean manifestCacheDirty = false; 1183 1184 1186 1189 public Manifest loadManifest(File jar) throws IOException { 1190 if (!usingManifestCache) { 1191 return super.loadManifest(jar); 1192 } 1193 if (manifestCache == null) { 1194 manifestCache = loadManifestCache(manifestCacheFile); 1195 } 1196 Object [] entry = manifestCache.get(jar); 1197 if (entry != null) { 1198 if (((Date )entry[0]).getTime() == jar.lastModified()) { 1199 Util.err.fine("Found manifest for " + jar + " in cache"); 1201 return (Manifest )entry[1]; 1202 } else { 1203 Util.err.fine("Wrong timestamp for " + jar + " in manifest cache"); 1204 } 1205 } else { 1206 Util.err.fine("No entry for " + jar + " in manifest cache"); 1207 } 1208 Manifest m = super.loadManifest(jar); 1210 manifestCache.put(jar, new Object [] {new Date (jar.lastModified()), m}); 1212 manifestCacheDirty = true; 1213 return m; 1214 } 1215 1216 1218 private void maybeSaveManifestCache() { 1219 if (usingManifestCache && manifestCacheDirty) { 1220 try { 1221 saveManifestCache(manifestCache, manifestCacheFile); 1222 } catch (IOException ioe) { 1223 Util.err.log(Level.WARNING, null, ioe); 1224 } 1225 usingManifestCache = false; 1226 manifestCacheDirty = false; 1227 manifestCache = null; 1228 manifestCacheFile = null; 1229 } 1230 } 1231 1232 1235 private void saveManifestCache(Map <File ,Object []> manifestCache, File manifestCacheFile) throws IOException { 1236 Util.err.fine("Saving manifest cache"); 1237 manifestCacheFile.getParentFile().mkdirs(); 1238 OutputStream os = new FileOutputStream (manifestCacheFile); 1239 try { 1240 try { 1241 os = new BufferedOutputStream (os); 1242 for (Map.Entry <File ,Object []> entry : manifestCache.entrySet()) { 1243 File jar = entry.getKey(); 1244 Object [] v = entry.getValue(); 1245 long time = ((Date )v[0]).getTime(); 1246 Manifest m = (Manifest )v[1]; 1247 os.write(jar.getAbsolutePath().getBytes("UTF-8")); os.write(0); 1249 for (int i = 7; i >= 0; i--) { 1250 os.write((int)((time >> (i * 8)) & 0xFF)); 1251 } 1252 m.write(os); 1253 os.write(0); 1254 } 1255 } finally { 1256 os.close(); 1257 } 1258 } catch (IOException ioe) { 1259 manifestCacheFile.delete(); 1261 throw ioe; 1262 } 1263 } 1264 1265 1270 private Map <File ,Object []> loadManifestCache(File manifestCacheFile) { 1271 if (!manifestCacheFile.canRead()) { 1272 Util.err.fine("No manifest cache found at " + manifestCacheFile); 1273 return new HashMap <File ,Object []>(200); 1274 } 1275 ev.log(Events.PERF_START, "NbInstaller - loadManifestCache"); try { 1277 InputStream is = new FileInputStream (manifestCacheFile); 1278 try { 1279 BufferedInputStream bis = new BufferedInputStream (is); 1280 Map <File ,Object []> m = new HashMap <File ,Object []>(200); 1281 ByteArrayOutputStream baos = new ByteArrayOutputStream ((int)manifestCacheFile.length()); 1282 FileUtil.copy(bis, baos); 1283 byte[] data = baos.toByteArray(); 1284 readManifestCacheEntries(data, m); 1285 return m; 1286 } finally { 1287 is.close(); 1288 ev.log(Events.PERF_END, "NbInstaller - loadManifestCache"); } 1290 } catch (IOException ioe) { 1291 Util.err.log(Level.WARNING, "While reading: " + manifestCacheFile, ioe); return new HashMap <File ,Object []>(200); 1293 } 1294 } 1295 1296 private static int findNullByte(byte[] data, int start) { 1297 int len = data.length; 1298 for (int i = start; i < len; i++) { 1299 if (data[i] == 0) { 1300 return i; 1301 } 1302 } 1303 return -1; 1304 } 1305 1306 private static void readManifestCacheEntries(byte[] data, Map <File ,Object []> m) throws IOException { 1307 int pos = 0; 1308 while (true) { 1309 if (pos == data.length) { 1310 return; 1311 } 1312 int end = findNullByte(data, pos); 1313 if (end == -1) throw new IOException ("Could not find next manifest JAR name from " + pos); File jar = new File (new String (data, pos, end - pos, "UTF-8")); long time = 0L; 1316 if (end + 8 >= data.length) throw new IOException ("Ran out of space for timestamp for " + jar); for (int i = 0; i < 8; i++) { 1318 long b = data[end + i + 1]; 1319 if (b < 0) b += 256; 1320 int exponent = 7 - i; 1321 long addin = b << (exponent * 8); 1322 time |= addin; 1323 } 1325 pos = end + 9; 1326 end = findNullByte(data, pos); 1327 if (end == -1) throw new IOException ("Could not find manifest body for " + jar); Manifest mani; 1329 try { 1330 mani = new Manifest (new ByteArrayInputStream (data, pos, end - pos)); 1331 } catch (IOException ioe) { 1332 Exceptions.attachMessage(ioe, "While in entry for " + jar); 1333 throw ioe; 1334 } 1335 m.put(jar, new Object [] {new Date (time), mani}); 1336 if (Util.err.isLoggable(Level.FINE)) { 1337 Util.err.fine("Manifest cache entry: jar=" + jar + " date=" + new Date (time) + " codename=" + mani.getMainAttributes().getValue("OpenIDE-Module")); 1338 } 1339 pos = end + 1; 1340 } 1341 } 1342 1343 1349 private void preresolveClasses(List <Module> modules) { 1350 Util.err.info("Pre-resolving classes for all loaded modules...be sure you have not specified -J-Xverify:none in ide.cfg"); 1351 for (Module m : modules) { 1352 if (m.isFixed()) continue; 1353 if (m.getJarFile() == null) continue; 1354 File jar = m.getJarFile(); 1355 try { 1357 JarFile j = new JarFile (jar, true); 1358 try { 1359 for (JarEntry entry : NbCollections.iterable(j.entries())) { 1360 String name = entry.getName(); 1361 if (name.endsWith(".class")) { String clazz = name.substring(0, name.length() - 6).replace('/', '.'); Throwable t = null; 1364 try { 1365 Class.forName(clazz, false, m.getClassLoader()); 1366 } catch (ClassNotFoundException cnfe) { t = cnfe; 1368 } catch (LinkageError le) { 1369 t = le; 1370 } catch (RuntimeException re) { t = re; 1372 } 1373 if (t != null) { 1374 Util.err.log(Level.WARNING, "From " + clazz + " in " + m.getCodeNameBase() + " with effective classpath " + getEffectiveClasspath(m), t); 1375 } 1376 } 1377 } 1378 } finally { 1379 j.close(); 1380 } 1381 } catch (IOException ioe) { 1382 Util.err.log(Level.WARNING, null, ioe); 1383 } 1384 } 1385 } 1386 1387} 1388 | Popular Tags |