1 19 20 package org.netbeans; 21 22 import java.io.*; 23 import java.util.*; 24 import java.util.logging.Level ; 25 import java.util.logging.Logger ; 26 import org.openide.util.*; 27 import org.openide.modules.*; 28 29 32 public abstract class Util { 33 34 private Util() {} 36 37 38 public static final Logger err = Logger.getLogger("org.netbeans.core.modules"); 40 43 static File makeTempJar(File moduleFile) throws IOException { 44 String prefix = moduleFile.getName(); 45 if (prefix.endsWith(".jar") || prefix.endsWith(".JAR")) { prefix = prefix.substring(0, prefix.length() - 4); 47 } 48 if (prefix.length() < 3) prefix += '.'; 49 if (prefix.length() < 3) prefix += '.'; 50 if (prefix.length() < 3) prefix += '.'; 51 String suffix = "-test.jar"; File physicalModuleFile = File.createTempFile(prefix, suffix); 53 physicalModuleFile.deleteOnExit(); 54 InputStream is = new FileInputStream(moduleFile); 55 try { 56 OutputStream os = new FileOutputStream(physicalModuleFile); 57 try { 58 byte[] buf = new byte[4096]; 59 int i; 60 while ((i = is.read(buf)) != -1) { 61 os.write(buf, 0, i); 62 } 63 } finally { 64 os.close(); 65 } 66 } finally { 67 is.close(); 68 } 69 err.fine("Made " + physicalModuleFile); 70 return physicalModuleFile; 71 } 72 73 76 static List<File> findLocaleVariantsOf(File f) { 77 List<FileWithSuffix> result = findLocaleVariantsWithSuffixesOf(f); 78 List<File> l = new ArrayList<File>(result.size()); 79 for (FileWithSuffix fws : result) { 80 l.add(fws.file); 81 } 82 return l; 83 } 84 static final class FileWithSuffix { 85 public final File file; 86 public final String suffix; 87 FileWithSuffix(File file, String suffix) { 88 this.file = file; 89 this.suffix = suffix; 90 } 91 } 92 95 static List<FileWithSuffix> findLocaleVariantsWithSuffixesOf(File f) { 96 if (! f.isFile()) { 97 return Collections.emptyList(); 98 } 99 File dir = new File(f.getParentFile(), "locale"); String logicalDir = null; 101 { 102 String logicalPath = findLogicalPath(f); 106 if (logicalPath != null) { 107 int slash = logicalPath.lastIndexOf('/'); 108 if (slash != -1) { 109 logicalDir = logicalPath.substring(0, slash + 1) + "locale/"; } else { 111 logicalDir = "locale/"; } 113 } 114 } 115 List<FileWithSuffix> l = new ArrayList<FileWithSuffix>(7); 116 String nameExt = f.getName(); 117 int idx = nameExt.lastIndexOf('.'); String name, ext; 119 if (idx != -1) { 120 name = nameExt.substring(0, idx); 121 ext = nameExt.substring(idx); 122 } else { 123 name = nameExt; 124 ext = ""; } 126 boolean localeDirExists = dir.exists(); 127 String [] suffixes = getLocalizingSuffixesFast(); 128 for (int i = 0; i < suffixes.length; i++) { 129 String suffix = suffixes[i]; 130 File v; 131 if (localeDirExists) { 132 v = new File(dir, name + suffix + ext); 133 if (v.isFile()) { 134 l.add(new FileWithSuffix(v, suffix)); 135 } 136 } else if (logicalDir != null) { 137 String path = logicalDir + name + suffix + ext; 138 v = InstalledFileLocator.getDefault().locate(path, null, false); 139 if (v != null) { 140 l.add(new FileWithSuffix(v, suffix)); 141 } 142 } 143 } 144 return l; 145 } 146 147 150 public static synchronized String [] getLocalizingSuffixesFast() { 151 if (suffixes == null || 152 Locale.getDefault() != lastLocale || 153 NbBundle.getBranding() != lastBranding) { 154 List<String > _suffixes = new ArrayList<String >(); 155 Iterator<String > it = NbBundle.getLocalizingSuffixes(); 156 while (it.hasNext()) { 157 _suffixes.add(it.next()); 158 } 159 suffixes = _suffixes.toArray(new String [_suffixes.size()]); 160 lastLocale = Locale.getDefault(); 161 lastBranding = NbBundle.getBranding(); 162 } 163 return suffixes; 164 } 165 private static String [] suffixes = null; 166 private static Locale lastLocale = null; 167 private static String lastBranding = null; 168 169 179 private static String findLogicalPath(File f) { 180 InstalledFileLocator l = InstalledFileLocator.getDefault(); 181 String path = f.getName(); 182 File parent = f.getParentFile(); 183 while (parent != null) { 184 File probe = l.locate(path, null, false); 185 if (f.equals(probe)) { 187 return path; 188 } 189 path = parent.getName() + '/' + path; 190 parent = parent.getParentFile(); 191 } 192 return null; 193 } 194 195 197 200 static boolean checkJavaDependency(Dependency dep) throws IllegalArgumentException { 201 if (dep.getType() == Dependency.TYPE_JAVA) { 203 if (dep.getName().equals(Dependency.JAVA_NAME)) { 204 if (dep.getComparison() == Dependency.COMPARE_SPEC) { 205 return new SpecificationVersion(dep.getVersion()).compareTo(Dependency.JAVA_SPEC) <= 0; 206 } else { 207 return dep.getVersion().equals(Dependency.JAVA_IMPL); 208 } 209 } else { 210 if (dep.getComparison() == Dependency.COMPARE_SPEC) { 211 return new SpecificationVersion(dep.getVersion()).compareTo(Dependency.VM_SPEC) <= 0; 212 } else { 213 return dep.getVersion().equals(Dependency.VM_IMPL); 214 } 215 } 216 } else { 217 throw new IllegalArgumentException (); 218 } 219 } 220 221 224 static boolean checkPackageDependency(Dependency dep, ClassLoader cl) throws IllegalArgumentException { 225 if (dep.getType() != Dependency.TYPE_PACKAGE) { 226 throw new IllegalArgumentException ("Not a package dependency"); } 228 if (! (cl instanceof Util.PackageAccessibleClassLoader) && cl != Util.class.getClassLoader()) { 229 throw new IllegalArgumentException ("Not a package-accessible classloader: " + cl); } 231 String name = dep.getName(); 232 String version = dep.getVersion(); 233 int comparison = dep.getComparison(); 234 String packageName, sampleName; 235 int idx = name.indexOf('['); 236 if (idx == -1) { 237 packageName = name; 238 sampleName = null; 239 } else if (idx == 0) { 240 packageName = null; 241 sampleName = name.substring(1, name.length() - 1); 242 } else { 243 packageName = name.substring(0, idx); 244 sampleName = name.substring(idx + 1, name.length() - 1); 245 if (sampleName.indexOf('.') == -1) { 246 sampleName = packageName + '.' + sampleName; 248 } 249 } 250 if (sampleName != null) { 251 try { 252 cl.loadClass(sampleName); 253 } catch (ClassNotFoundException cnfe) { 254 if (packageName == null) { 255 err.log(Level.WARNING, null, cnfe); 257 err.fine("Probed class could not be found"); 258 return false; 259 } 260 } catch (RuntimeException e) { 263 err.log(Level.WARNING, null, e); 265 err.fine("Assuming package " + packageName + " is corrupt"); 266 return false; 267 } catch (LinkageError le) { 268 err.log(Level.WARNING, null, le); 270 err.fine("Assuming package " + packageName + " is corrupt"); 271 return false; 272 } 273 } 274 if (packageName != null) { 275 Package pkg; 276 if (cl instanceof Util.PackageAccessibleClassLoader) { 277 pkg = ((Util.PackageAccessibleClassLoader)cl).getPackageAccessibly(packageName); 278 } else { 279 pkg = Package.getPackage(packageName); 280 } 281 if (pkg == null) { 282 err.fine("No package with the name " + packageName + " found"); 283 return false; 284 } 285 if (comparison == Dependency.COMPARE_ANY) { 286 return true; 287 } else if (comparison == Dependency.COMPARE_SPEC) { 288 if (pkg.getSpecificationVersion() == null) { 289 err.fine("Package " + packageName + " did not give a specification version"); 290 return false; 291 } else { 292 try { 293 SpecificationVersion versionSpec = new SpecificationVersion(version); 294 SpecificationVersion pkgSpec = new SpecificationVersion(pkg.getSpecificationVersion().trim()); 295 if (versionSpec.compareTo(pkgSpec) <= 0) { 296 return true; 297 } else { 298 err.fine("Loaded package " + packageName + " was only of version " + pkgSpec + " but " + versionSpec + " was requested"); 299 return false; 300 } 301 } catch (NumberFormatException nfe) { 302 err.log(Level.WARNING, null, nfe); 303 err.fine("Will not honor a dependency on non-numeric package spec version"); 304 return false; 305 } 306 } 307 } else { 308 if (pkg.getImplementationVersion() == null) { 310 err.fine("Package " + packageName + " had no implementation version"); 311 return false; 312 } else if (! pkg.getImplementationVersion().trim().equals(version)) { 313 err.fine("Package " + packageName + " had the wrong impl version: " + pkg.getImplementationVersion()); 314 return false; 315 } else { 316 return true; 317 } 318 } 319 } else { 320 return true; 322 } 323 } 324 325 329 public interface PackageAccessibleClassLoader { 330 331 Package getPackageAccessibly (String name); 332 333 Package [] getPackagesAccessibly (); 334 } 335 336 340 public interface ModuleProvider { 341 Module getModule(); 342 } 343 344 355 public static Map<Module,List<Module>> moduleDependencies(Collection<Module> modules, Map<String ,Module> modulesByName, Map<String ,Set<Module>> _providersOf) { 356 Set<Module> modulesSet = (modules instanceof Set) ? (Set<Module>)modules : new HashSet<Module>(modules); 357 Map<String ,List<Module>> providersOf = new HashMap<String ,List<Module>>(_providersOf.size() * 2 + 1); 358 for (Map.Entry<String , Set<Module>> entry: _providersOf.entrySet()) { 359 Set<Module> providers = entry.getValue(); 360 if (providers != null) { 361 List<Module> availableProviders = new LinkedList<Module>(providers); 362 availableProviders.retainAll(modulesSet); 363 if (!availableProviders.isEmpty()) { 364 providersOf.put(entry.getKey(), availableProviders); 365 } 366 } 367 } 368 Map<Module,List<Module>> m = new HashMap<Module,List<Module>>(); 369 for (Module m1: modules) { 370 List<Module> l = null; 371 Dependency[] dependencies = m1.getDependenciesArray(); 372 for (int i = 0; i < dependencies.length; i++) { 373 Dependency dep = dependencies[i]; 374 375 if (dep.getType() == Dependency.TYPE_REQUIRES) { 376 List<Module> providers = providersOf.get(dep.getName()); 377 378 if (providers != null) { 379 if (l == null) { 380 l = new LinkedList<Module>(); 381 } 382 l.addAll(providers); 383 } 384 } 385 else if (dep.getType() == Dependency.TYPE_MODULE) { 386 String cnb = (String ) parseCodeName(dep.getName())[0]; 387 Module m2 = modulesByName.get(cnb); 388 389 if (m2 != null && modulesSet.contains(m2)) { 390 if (l == null) { 391 l = new LinkedList<Module>(); 392 } 393 l.add(m2); 394 } 395 } 396 } 397 if (l != null) { 398 m.put(m1, l); 399 } 400 } 401 return m; 402 } 403 404 409 static Set<Module> moduleInterdependencies(Module m, boolean reverse, boolean transitive, 410 Set<Module> modules, Map<String ,Module> modulesByName, Map<String ,Set<Module>> providersOf) { 411 if (reverse) { 414 Set<Module> s = new HashSet<Module>(); 415 for (Module m2: modules) { 416 if (m2 == m) { 417 continue; 418 } 419 if (moduleInterdependencies(m2, false, transitive, modules, modulesByName, providersOf).contains(m)) { 420 s.add(m2); 421 } 422 } 423 return s; 424 } else { 425 Set<Module> s = new HashSet<Module>(); 426 Dependency[] dependencies = m.getDependenciesArray(); 427 for (int i = 0; i < dependencies.length; i++) { 428 Dependency dep = dependencies[i]; 429 if (dep.getType() == Dependency.TYPE_REQUIRES) { 430 Set<Module> providers = providersOf.get(dep.getName()); 431 if (providers != null) { 432 s.addAll(providers); 433 } 434 } else if (dep.getType() == Dependency.TYPE_MODULE) { 435 String cnb = (String )parseCodeName(dep.getName())[0]; 436 Module m2 = modulesByName.get(cnb); 437 if (m2 != null) { 438 s.add(m2); 439 } 440 } 441 } 442 s.remove(m); 443 if (transitive) { 444 Set<Module> toAdd; 445 do { 446 toAdd = new HashSet<Module>(); 447 for (Module m2: s) { 448 Set<Module> s2 = moduleInterdependencies(m2, false, false, modules, modulesByName, providersOf); 449 s2.remove(m); 450 s2.removeAll(s); 451 toAdd.addAll(s2); 452 } 453 s.addAll(toAdd); 454 } while (!toAdd.isEmpty()); 455 } 456 return s; 457 } 458 } 459 460 462 static Comparator displayNameComparator() { 463 return new DisplayNameComparator(); 464 } 465 private static final class DisplayNameComparator implements Comparator { 466 DisplayNameComparator() {} 467 public int compare(Object o1, Object o2) { 468 Module m1 = (Module)o1; 469 Module m2 = (Module)o2; 470 return m1.getDisplayName().compareTo(m2.getDisplayName()); 471 } 472 } 473 474 480 public static String findLocalizedMessage(Throwable t, boolean detailOK) { 481 String locmsg = t.getLocalizedMessage(); 482 if (Utilities.compareObjects(locmsg, t.getMessage())) { 483 locmsg = Exceptions.findLocalizedMessage(t); 484 if (! detailOK) { 485 return null; 486 } 487 } 488 return locmsg; 489 } 490 491 492 static FilenameFilter jarFilter() { 493 return new JarFilter(); 494 } 495 private static final class JarFilter implements FilenameFilter { 496 JarFilter() {} 497 public boolean accept(File dir, String name) { 498 String n = name.toLowerCase(Locale.US); 499 return n.endsWith(".jar"); } 501 } 502 503 509 public static String createPackageName(String name) throws IllegalArgumentException { 510 String clExt = ".class"; if (!name.endsWith(clExt)) { 512 clExt = ".ser"; } 515 if (name.endsWith(clExt)) { 516 String bareName = name.substring(0, name.length() - clExt.length()); 517 if (bareName.length() == 0) { throw new IllegalArgumentException ("Bad class file name: " + name); } 520 if (bareName.charAt(0) == '/') { throw new IllegalArgumentException ("Bad class file name: " + name); } 523 if (bareName.charAt(bareName.length() - 1) == '/') { throw new IllegalArgumentException ("Bad class file name: " + name); } 526 if (bareName.indexOf('.') != -1) { throw new IllegalArgumentException ("Bad class file name: " + name); } 529 return bareName.replace('/', '.'); } else { throw new IllegalArgumentException ("Bad class file name: " + name); } 533 } 534 535 543 static final class ModuleLookup extends Lookup { 544 ModuleLookup() {} 545 private final Set<Module> modules = new HashSet<Module>(100); 546 private final Set<ModuleResult> results = new WeakSet<ModuleResult>(10); 547 548 public void add(Module m) { 549 synchronized (modules) { 550 modules.add(m); 551 } 552 } 553 554 public void remove(Module m) { 555 synchronized (modules) { 556 modules.remove(m); 557 } 558 } 559 560 public void changed() { 561 synchronized (results) { 562 Iterator it = results.iterator(); 563 while (it.hasNext()) { 564 ((ModuleResult)it.next()).changed(); 565 } 566 } 567 } 568 public <T> T lookup(Class <T> clazz) { 569 if ((clazz == Module.class || clazz == ModuleInfo.class || clazz == Object .class || clazz == null) 570 && ! modules.isEmpty()) { 571 synchronized (modules) { 572 return clazz.cast(modules.iterator().next()); 573 } 574 } else { 575 return null; 576 } 577 } 578 @SuppressWarnings ("unchecked") 579 public <T> Lookup.Result<T> lookup(Lookup.Template<T> t) { 580 Class <T> clazz = t.getType(); 581 if (clazz == Module.class || clazz == ModuleInfo.class || 582 clazz == Object .class || clazz == null) { 583 return (Lookup.Result<T>)(Object ) new ModuleResult((Lookup.Template<Module>) t); 584 } 585 else { 586 return Lookup.EMPTY.lookup(t); 587 } 588 } 589 public String toString() { 590 synchronized (modules) { 591 return "ModuleLookup" + modules; } 593 } 594 private final class ModuleResult extends Lookup.Result<Module> { 595 private final Lookup.Template<? super Module> t; 596 private final Set<LookupListener> listeners = new HashSet<LookupListener>(10); 597 public ModuleResult(Lookup.Template<? super Module> t) { 598 this.t = t; 599 synchronized (results) { 600 results.add(this); 601 } 602 } 603 public void addLookupListener(LookupListener l) { 604 synchronized (listeners) { 605 listeners.add(l); 606 } 607 } 608 public void removeLookupListener(LookupListener l) { 609 synchronized (listeners) { 610 listeners.remove(l); 611 } 612 } 613 public void changed() { 614 LookupListener[] _listeners; 615 synchronized (listeners) { 616 if (listeners.isEmpty()) { 617 return; 618 } 619 _listeners = listeners.toArray(new LookupListener[listeners.size()]); 620 } 621 LookupEvent ev = new LookupEvent(this); 622 for (int i = 0; i < _listeners.length; i++) { 623 _listeners[i].resultChanged(ev); 624 } 625 } 626 public Collection<Module> allInstances() { 627 synchronized (modules) { 628 String id = t.getId(); 629 Object inst = t.getInstance(); 630 if (id != null) { 631 Iterator<Module> it = modules.iterator(); 632 while (it.hasNext()) { 633 Module m = it.next(); 634 if (id.equals(ModuleItem.PREFIX + m.getCodeNameBase())) { 635 if (inst == null || inst == m) { 636 return Collections.<Module>singleton(m); 637 } 638 } 639 } 640 return Collections.<Module>emptySet(); 641 } else if (inst != null) { 642 return modules.contains(inst) ? Collections.<Module>singleton(Module.class.cast(inst)) : Collections.<Module>emptySet(); 643 } else { 644 return new HashSet<Module>(modules); 646 } 647 } 648 } 649 public Set<Class <? extends Module>> allClasses() { 650 return Collections.<Class <? extends Module>>singleton(Module.class); 651 } 652 public Collection<? extends Lookup.Item<Module>> allItems() { 653 Collection<Module> insts = allInstances(); 654 ArrayList<ModuleItem> list = new ArrayList<ModuleItem>(Math.max(1, insts.size())); 655 for (Module m: insts) { 656 list.add(new ModuleItem(m)); 657 } 658 return list; 659 } 660 public String toString() { 661 return "ModuleResult:" + t; } 663 } 664 private static final class ModuleItem extends Lookup.Item<Module> { 665 public static final String PREFIX = "Module["; private final Module item; 667 public ModuleItem(Module item) { 668 this.item = item; 669 } 670 public Module getInstance() { 671 return item; 672 } 673 public Class <? extends Module> getType() { 674 return Module.class; 675 } 676 public String getId() { 677 return PREFIX + item.getCodeNameBase(); 678 } 679 public String getDisplayName() { 680 return item.getDisplayName(); 681 } 682 } 683 } 684 685 private static final Map<String ,Object []> codeNameParseCache = new HashMap<String ,Object []>(200); 694 public static Object [] parseCodeName(String cn) throws NumberFormatException { 695 synchronized (codeNameParseCache) { 696 Object [] r = codeNameParseCache.get(cn); 697 if (r == null) { 698 r = new Object [3]; 699 int i = cn.lastIndexOf('/'); 700 if (i == -1) { 701 r[0] = cn; 702 } else { 703 r[0] = cn.substring(0, i).intern(); 704 String end = cn.substring(i + 1); 705 int j = end.indexOf('-'); 706 if (j == -1) { 707 r[1] = new Integer (end); 708 } else { 709 r[1] = new Integer (end.substring(0, j)); 710 r[2] = new Integer (end.substring(j + 1)); 711 } 712 } 713 codeNameParseCache.put(cn.intern(), r); 714 } 715 return r; 716 } 717 } 718 719 725 public static SpecificationVersion getModuleDep(Set dependencies, String cnb) { 726 Iterator it = dependencies.iterator(); 727 while (it.hasNext()) { 728 Dependency d = (Dependency)it.next(); 729 if (d.getType() == Dependency.TYPE_MODULE && 730 d.getComparison() == Dependency.COMPARE_SPEC) { 731 try { 732 Object [] p = parseCodeName(d.getName()); 733 if (!p[0].equals(cnb)) { 734 continue; 735 } 736 int rel = ((Integer )p[1]).intValue(); if (rel == -1) rel = 0; return new SpecificationVersion("" + rel + "." + d.getVersion()); } catch (NumberFormatException nfe) { 740 Util.err.log(Level.WARNING, null, nfe); 741 return null; 742 } 743 } 744 } 745 return null; 746 } 747 748 756 public static void transitiveClosureModuleDependencies(ModuleManager mgr, Set<Module> modules) { 757 Set<Module> nue = null; while (nue == null || !nue.isEmpty()) { 759 nue = new HashSet<Module>(); 760 for (Module m: modules) { 761 Dependency[] deps = m.getDependenciesArray(); 762 for (int i = 0; i < deps.length; i++) { 763 if (deps[i].getType() != Dependency.TYPE_MODULE) { 764 continue; 765 } 766 Module other = mgr.get((String )parseCodeName(deps[i].getName())[0]); 767 if (other != null && !modules.contains(other)) { 768 nue.add(other); 769 } 770 } 771 } 772 modules.addAll(nue); 773 } 774 } 775 776 } 777 | Popular Tags |