| 1 7 8 package java.security; 9 10 import java.io.*; 11 import java.util.*; 12 import static java.util.Locale.ENGLISH ; 13 import java.lang.ref.*; 14 import java.lang.reflect.*; 15 16 import java.security.cert.CertStoreParameters ; 17 18 69 public abstract class Provider extends Properties { 70 71 static final long serialVersionUID = -4298000515446427739L; 73 74 private static final sun.security.util.Debug debug = 75 sun.security.util.Debug.getInstance 76 ("provider", "Provider"); 77 78 83 private String name; 84 85 90 private String info; 91 92 97 private double version; 98 99 100 private transient Set entrySet = null; 101 private transient int entrySetCallCount = 0; 102 103 104 114 protected Provider(String name, double version, String info) { 115 this.name = name; 116 this.version = version; 117 this.info = info; 118 putId(); 119 } 120 121 126 public String getName() { 127 return name; 128 } 129 130 135 public double getVersion() { 136 return version; 137 } 138 139 145 public String getInfo() { 146 return info; 147 } 148 149 156 public String toString() { 157 return name + " version " + version; 158 } 159 160 165 166 187 public synchronized void clear() { 188 check("clearProviderProperties."+name); 189 if (debug != null) { 190 debug.println("Remove " + name + " provider properties"); 191 } 192 implClear(); 193 } 194 195 203 public synchronized void load(InputStream inStream) throws IOException { 204 check("putProviderProperty."+name); 205 if (debug != null) { 206 debug.println("Load " + name + " provider properties"); 207 } 208 Properties tempProperties = new Properties(); 209 tempProperties.load(inStream); 210 implPutAll(tempProperties); 211 } 212 213 220 public synchronized void putAll(Map<?,?> t) { 221 check("putProviderProperty."+name); 222 if (debug != null) { 223 debug.println("Put all " + name + " provider properties"); 224 } 225 implPutAll(t); 226 } 227 228 235 public synchronized Set<Map.Entry<Object ,Object >> entrySet() { 236 if (entrySet == null) { 237 if (entrySetCallCount++ == 0) entrySet = Collections.unmodifiableMap(this).entrySet(); 239 else 240 return super.entrySet(); } 242 243 if (entrySetCallCount != 2) 249 throw new RuntimeException ("Internal error."); 250 251 return entrySet; 252 } 253 254 260 public Set<Object > keySet() { 261 return Collections.unmodifiableSet(super.keySet()); 262 } 263 264 270 public Collection<Object > values() { 271 return Collections.unmodifiableCollection(super.values()); 272 } 273 274 302 public synchronized Object put(Object key, Object value) { 303 check("putProviderProperty."+name); 304 if (debug != null) { 305 debug.println("Set " + name + " provider property [" + 306 key + "/" + value +"]"); 307 } 308 return implPut(key, value); 309 } 310 311 338 public synchronized Object remove(Object key) { 339 check("removeProviderProperty."+name); 340 if (debug != null) { 341 debug.println("Remove " + name + " provider property " + key); 342 } 343 return implRemove(key); 344 } 345 346 private static void check(String directive) { 347 SecurityManager security = System.getSecurityManager(); 348 if (security != null) { 349 security.checkSecurityAccess(directive); 350 } 351 } 352 353 private transient boolean legacyChanged; 355 private transient boolean servicesChanged; 357 358 private transient Map<String ,String > legacyStrings; 360 361 private transient Map<ServiceKey,Service> serviceMap; 364 365 private transient Map<ServiceKey,Service> legacyMap; 368 369 private transient Set<Service> serviceSet; 372 373 private void putId() { 377 super.put("Provider.id name", String.valueOf(name)); 379 super.put("Provider.id version", String.valueOf(version)); 380 super.put("Provider.id info", String.valueOf(info)); 381 super.put("Provider.id className", this.getClass().getName()); 382 } 383 384 389 private void implPutAll(Map t) { 390 for (Map.Entry e : ((Map<?,?>)t).entrySet()) { 391 implPut(e.getKey(), e.getValue()); 392 } 393 } 394 395 private Object implRemove(Object key) { 396 if (key instanceof String ) { 397 String keyString = (String )key; 398 if (keyString.startsWith("Provider.")) { 399 return null; 400 } 401 legacyChanged = true; 402 if (legacyStrings == null) { 403 legacyStrings = new LinkedHashMap<String ,String >(); 404 } 405 legacyStrings.remove(keyString); 406 } 407 return super.remove(key); 408 } 409 410 private Object implPut(Object key, Object value) { 411 if ((key instanceof String ) && (value instanceof String )) { 412 String keyString = (String )key; 413 if (keyString.startsWith("Provider.")) { 414 return null; 415 } 416 legacyChanged = true; 417 if (legacyStrings == null) { 418 legacyStrings = new LinkedHashMap<String ,String >(); 419 } 420 legacyStrings.put(keyString, (String )value); 421 } 422 return super.put(key, value); 423 } 424 425 private void implClear() { 426 super.clear(); 427 putId(); 428 if (legacyStrings != null) { 429 legacyStrings.clear(); 430 } 431 if (legacyMap != null) { 432 legacyMap.clear(); 433 } 434 if (serviceMap != null) { 435 serviceMap.clear(); 436 } 437 legacyChanged = false; 438 servicesChanged = false; 439 serviceSet = null; 440 } 441 442 private static class ServiceKey { 444 private final String type; 445 private final String algorithm; 446 private final String originalAlgorithm; 447 private ServiceKey(String type, String algorithm, boolean intern) { 448 this.type = type; 449 this.originalAlgorithm = algorithm; 450 algorithm = algorithm.toUpperCase(ENGLISH); 451 this.algorithm = intern ? algorithm.intern() : algorithm; 452 } 453 public int hashCode() { 454 return type.hashCode() + algorithm.hashCode(); 455 } 456 public boolean equals(Object obj) { 457 if (this == obj) { 458 return true; 459 } 460 if (obj instanceof ServiceKey == false) { 461 return false; 462 } 463 ServiceKey other = (ServiceKey)obj; 464 return this.type.equals(other.type) 465 && this.algorithm.equals(other.algorithm); 466 } 467 boolean matches(String type, String algorithm) { 468 return (this.type == type) && (this.originalAlgorithm == algorithm); 469 } 470 } 471 472 476 private void ensureLegacyParsed() { 477 if ((legacyChanged == false) || (legacyStrings == null)) { 478 return; 479 } 480 serviceSet = null; 481 if (legacyMap == null) { 482 legacyMap = new LinkedHashMap<ServiceKey,Service>(); 483 } else { 484 legacyMap.clear(); 485 } 486 for (Map.Entry<String ,String > entry : legacyStrings.entrySet()) { 487 parseLegacyPut(entry.getKey(), entry.getValue()); 488 } 489 removeInvalidServices(legacyMap); 490 legacyChanged = false; 491 } 492 493 497 private void removeInvalidServices(Map<ServiceKey,Service> map) { 498 for (Iterator t = map.entrySet().iterator(); t.hasNext(); ) { 499 Map.Entry entry = (Map.Entry)t.next(); 500 Service s = (Service)entry.getValue(); 501 if (s.isValid() == false) { 502 t.remove(); 503 } 504 } 505 } 506 507 private String [] getTypeAndAlgorithm(String key) { 508 int i = key.indexOf("."); 509 if (i < 1) { 510 if (debug != null) { 511 debug.println("Ignoring invalid entry in provider " 512 + name + ":" + key); 513 } 514 return null; 515 } 516 String type = key.substring(0, i); 517 String alg = key.substring(i + 1); 518 return new String [] {type, alg}; 519 } 520 521 private final static String ALIAS_PREFIX = "Alg.Alias."; 522 private final static String ALIAS_PREFIX_LOWER = "alg.alias."; 523 private final static int ALIAS_LENGTH = ALIAS_PREFIX.length(); 524 525 private void parseLegacyPut(String name, String value) { 526 if (name.toLowerCase(ENGLISH).startsWith(ALIAS_PREFIX_LOWER)) { 527 String stdAlg = value; 530 String aliasKey = name.substring(ALIAS_LENGTH); 531 String [] typeAndAlg = getTypeAndAlgorithm(aliasKey); 532 if (typeAndAlg == null) { 533 return; 534 } 535 String type = getEngineName(typeAndAlg[0]); 536 String aliasAlg = typeAndAlg[1].intern(); 537 ServiceKey key = new ServiceKey(type, stdAlg, true); 538 Service s = (Service)legacyMap.get(key); 539 if (s == null) { 540 s = new Service(this); 541 s.type = type; 542 s.algorithm = stdAlg; 543 legacyMap.put(key, s); 544 } 545 legacyMap.put(new ServiceKey(type, aliasAlg, true), s); 546 s.addAlias(aliasAlg); 547 } else { 548 String [] typeAndAlg = getTypeAndAlgorithm(name); 549 if (typeAndAlg == null) { 550 return; 551 } 552 int i = typeAndAlg[1].indexOf(' '); 553 if (i == -1) { 554 String type = getEngineName(typeAndAlg[0]); 556 String stdAlg = typeAndAlg[1].intern(); 557 String className = value; 558 ServiceKey key = new ServiceKey(type, stdAlg, true); 559 Service s = (Service)legacyMap.get(key); 560 if (s == null) { 561 s = new Service(this); 562 s.type = type; 563 s.algorithm = stdAlg; 564 legacyMap.put(key, s); 565 } 566 s.className = className; 567 } else { String attributeValue = value; 570 String type = getEngineName(typeAndAlg[0]); 571 String attributeString = typeAndAlg[1]; 572 String stdAlg = attributeString.substring(0, i).intern(); 573 String attributeName = attributeString.substring(i + 1); 574 while (attributeName.startsWith(" ")) { 576 attributeName = attributeName.substring(1); 577 } 578 attributeName = attributeName.intern(); 579 ServiceKey key = new ServiceKey(type, stdAlg, true); 580 Service s = (Service)legacyMap.get(key); 581 if (s == null) { 582 s = new Service(this); 583 s.type = type; 584 s.algorithm = stdAlg; 585 legacyMap.put(key, s); 586 } 587 s.addAttribute(attributeName, attributeValue); 588 } 589 } 590 } 591 592 612 public synchronized Service getService(String type, String algorithm) { 613 ServiceKey key = previousKey; 615 if (key.matches(type, algorithm) == false) { 616 key = new ServiceKey(type, algorithm, false); 617 previousKey = key; 618 } 619 if (serviceMap != null) { 620 Service service = serviceMap.get(key); 621 if (service != null) { 622 return service; 623 } 624 } 625 ensureLegacyParsed(); 626 return (legacyMap != null) ? legacyMap.get(key) : null; 627 } 628 629 private static volatile ServiceKey previousKey = 636 new ServiceKey("", "", false); 637 638 647 public synchronized Set<Service> getServices() { 648 if (legacyChanged || servicesChanged) { 649 serviceSet = null; 650 } else if (serviceSet != null) { 651 return serviceSet; 652 } 653 ensureLegacyParsed(); 654 serviceSet = new LinkedHashSet<Service>(); 655 if (serviceMap != null) { 656 serviceSet.addAll(serviceMap.values()); 657 } 658 if (legacyMap != null) { 659 serviceSet.addAll(legacyMap.values()); 660 } 661 servicesChanged = false; 662 return serviceSet; 663 } 664 665 694 protected synchronized void putService(Service s) { 695 check("putProviderProperty." + name); 696 if (debug != null) { 697 debug.println(name + ".putService(): " + s); 698 } 699 if (s == null) { 700 throw new NullPointerException (); 701 } 702 if (serviceMap == null) { 703 serviceMap = new LinkedHashMap<ServiceKey,Service>(); 704 } 705 servicesChanged = true; 706 String type = s.getType(); 707 String algorithm = s.getAlgorithm(); 708 ServiceKey key = new ServiceKey(type, algorithm, true); 709 implRemoveService(serviceMap.get(key)); 711 serviceMap.put(key, s); 712 for (String alias : s.getAliases()) { 713 serviceMap.put(new ServiceKey(type, alias, true), s); 714 } 715 putPropertyStrings(s); 716 } 717 718 722 private void putPropertyStrings(Service s) { 723 String type = s.getType(); 724 String algorithm = s.getAlgorithm(); 725 super.put(type + "." + algorithm, s.getClassName()); 727 for (String alias : s.getAliases()) { 728 super.put(ALIAS_PREFIX + type + "." + alias, algorithm); 729 } 730 for (Map.Entry<UString,String > entry : s.attributes.entrySet()) { 731 String key = type + "." + algorithm + " " + entry.getKey(); 732 super.put(key, entry.getValue()); 733 } 734 } 735 736 740 private void removePropertyStrings(Service s) { 741 String type = s.getType(); 742 String algorithm = s.getAlgorithm(); 743 super.remove(type + "." + algorithm); 745 for (String alias : s.getAliases()) { 746 super.remove(ALIAS_PREFIX + type + "." + alias); 747 } 748 for (Map.Entry<UString,String > entry : s.attributes.entrySet()) { 749 String key = type + "." + algorithm + " " + entry.getKey(); 750 super.remove(key); 751 } 752 } 753 754 782 protected synchronized void removeService(Service s) { 783 check("removeProviderProperty." + name); 784 if (debug != null) { 785 debug.println(name + ".removeService(): " + s); 786 } 787 if (s == null) { 788 throw new NullPointerException (); 789 } 790 implRemoveService(s); 791 } 792 793 private void implRemoveService(Service s) { 794 if ((s == null) || (serviceMap == null)) { 795 return; 796 } 797 String type = s.getType(); 798 String algorithm = s.getAlgorithm(); 799 ServiceKey key = new ServiceKey(type, algorithm, false); 800 Service oldService = serviceMap.get(key); 801 if (s != oldService) { 802 return; 803 } 804 servicesChanged = true; 805 serviceMap.remove(key); 806 for (String alias : s.getAliases()) { 807 serviceMap.remove(new ServiceKey(type, alias, false)); 808 } 809 removePropertyStrings(s); 810 } 811 812 private static class UString { 814 final String string; 815 final String lowerString; 816 817 UString(String s) { 818 this.string = s; 819 this.lowerString = s.toLowerCase(ENGLISH); 820 } 821 822 public int hashCode() { 823 return lowerString.hashCode(); 824 } 825 826 public boolean equals(Object obj) { 827 if (this == obj) { 828 return true; 829 } 830 if (obj instanceof UString == false) { 831 return false; 832 } 833 UString other = (UString)obj; 834 return lowerString.equals(other.lowerString); 835 } 836 837 public String toString() { 838 return string; 839 } 840 } 841 842 private static class EngineDescription { 844 final String name; 845 final boolean constructor; 846 final boolean supportsParameter; 847 848 EngineDescription(String name, boolean constructor, boolean sp) { 849 this.name = name; 850 this.constructor = constructor; 851 this.supportsParameter = sp; 852 } 853 } 854 855 private static final Map<String ,EngineDescription> knownEngines; 857 858 private static void addEngine(String name, boolean cons, boolean sp) { 859 EngineDescription ed = new EngineDescription(name, cons, sp); 860 knownEngines.put(name.toLowerCase(ENGLISH), ed); 862 knownEngines.put(name, ed); 863 } 864 865 static { 866 knownEngines = new HashMap<String ,EngineDescription>(); 867 addEngine("AlgorithmParameterGenerator", false, false); 869 addEngine("AlgorithmParameters", false, false); 870 addEngine("KeyFactory", false, false); 871 addEngine("KeyPairGenerator", false, false); 872 addEngine("KeyStore", false, false); 873 addEngine("MessageDigest", false, false); 874 addEngine("SecureRandom", false, false); 875 addEngine("Signature", false, true); 876 addEngine("CertificateFactory", false, false); 877 addEngine("CertPathBuilder", false, false); 878 addEngine("CertPathValidator", false, false); 879 addEngine("CertStore", true, false); 880 addEngine("Cipher", false, true); 882 addEngine("ExemptionMechanism", false, false); 883 addEngine("Mac", false, true); 884 addEngine("KeyAgreement", false, true); 885 addEngine("KeyGenerator", false, false); 886 addEngine("SecretKeyFactory", false, false); 887 addEngine("KeyManagerFactory", false, false); 889 addEngine("SSLContext", false, false); 890 addEngine("TrustManagerFactory", false, false); 891 addEngine("GssApiMechanism", false, false); 893 addEngine("SaslClientFactory", false, false); 895 addEngine("SaslServerFactory", false, false); 896 } 897 898 private static String getEngineName(String s) { 901 EngineDescription e = knownEngines.get(s); 903 if (e == null) { 904 e = knownEngines.get(s.toLowerCase(ENGLISH)); 905 } 906 return (e == null) ? s : e.name; 907 } 908 909 |