632 firstSearch = false;
633 }
634
635 if ((newCandidates != null) && !newCandidates.isEmpty()) {
636 // For each provider in the candidates set, if it
637 // isn't in the newCandidate set, we should remove
638 // it from the candidate set.
639 for (Iterator<Provider> cansIte = candidates.iterator();
640 cansIte.hasNext(); ) {
641 Provider prov = cansIte.next();
642 if (!newCandidates.contains(prov)) {
643 cansIte.remove();
644 }
645 }
646 } else {
647 candidates = null;
648 break;
649 }
650 }
651
652 if ((candidates == null) || (candidates.isEmpty()))
653 return null;
654
655 Object[] candidatesArray = candidates.toArray();
656 Provider[] result = new Provider[candidatesArray.length];
657
658 for (int i = 0; i < result.length; i++) {
659 result[i] = (Provider)candidatesArray[i];
660 }
661
662 return result;
663 }
664
665 // Map containing cached Spi Class objects of the specified type
666 private static final Map<String, Class<?>> spiMap =
667 new ConcurrentHashMap<>();
668
669 /**
670 * Return the Class object for the given engine type
671 * (e.g. "MessageDigest"). Works for Spis in the java.security package
672 * only.
988 if (attribute.equalsIgnoreCase("ImplementedIn")) {
989 return value.equalsIgnoreCase(prop);
990 }
991
992 return false;
993 }
994
995 static String[] getFilterComponents(String filterKey, String filterValue) {
996 int algIndex = filterKey.indexOf('.');
997
998 if (algIndex < 0) {
999 // There must be a dot in the filter, and the dot
1000 // shouldn't be at the beginning of this string.
1001 throw new InvalidParameterException("Invalid filter");
1002 }
1003
1004 String serviceName = filterKey.substring(0, algIndex);
1005 String algName = null;
1006 String attrName = null;
1007
1008 if (filterValue.length() == 0) {
1009 // The filterValue is an empty string. So the filterKey
1010 // should be in the format of <crypto_service>.<algorithm_or_type>.
1011 algName = filterKey.substring(algIndex + 1).trim();
1012 if (algName.length() == 0) {
1013 // There must be a algorithm or type name.
1014 throw new InvalidParameterException("Invalid filter");
1015 }
1016 } else {
1017 // The filterValue is a non-empty string. So the filterKey must be
1018 // in the format of
1019 // <crypto_service>.<algorithm_or_type> <attribute_name>
1020 int attrIndex = filterKey.indexOf(' ');
1021
1022 if (attrIndex == -1) {
1023 // There is no attribute name in the filter.
1024 throw new InvalidParameterException("Invalid filter");
1025 } else {
1026 attrName = filterKey.substring(attrIndex + 1).trim();
1027 if (attrName.length() == 0) {
1028 // There is no attribute name in the filter.
1029 throw new InvalidParameterException("Invalid filter");
1030 }
1031 }
1032
1033 // There must be an algorithm name in the filter.
1034 if ((attrIndex < algIndex) ||
1035 (algIndex == attrIndex - 1)) {
1036 throw new InvalidParameterException("Invalid filter");
1037 } else {
1038 algName = filterKey.substring(algIndex + 1, attrIndex);
1039 }
1040 }
1041
1042 String[] result = new String[3];
1043 result[0] = serviceName;
1044 result[1] = algName;
1045 result[2] = attrName;
1046
1047 return result;
1053 * (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). Returns
1054 * an empty Set if there is no provider that supports the
1055 * specified service or if serviceName is null. For a complete list
1056 * of Java cryptographic services, please see the
1057 * {@extLink security_guide_jca
1058 * Java Cryptography Architecture (JCA) Reference Guide}.
1059 * Note: the returned set is immutable.
1060 *
1061 * @param serviceName the name of the Java cryptographic
1062 * service (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore).
1063 * Note: this parameter is case-insensitive.
1064 *
1065 * @return a Set of Strings containing the names of all available
1066 * algorithms or types for the specified Java cryptographic service
1067 * or an empty set if no provider supports the specified service.
1068 *
1069 * @since 1.4
1070 **/
1071 public static Set<String> getAlgorithms(String serviceName) {
1072
1073 if ((serviceName == null) || (serviceName.length() == 0) ||
1074 (serviceName.endsWith("."))) {
1075 return Collections.emptySet();
1076 }
1077
1078 HashSet<String> result = new HashSet<>();
1079 Provider[] providers = Security.getProviders();
1080
1081 for (int i = 0; i < providers.length; i++) {
1082 // Check the keys for each provider.
1083 for (Enumeration<Object> e = providers[i].keys();
1084 e.hasMoreElements(); ) {
1085 String currentKey =
1086 ((String)e.nextElement()).toUpperCase(Locale.ENGLISH);
1087 if (currentKey.startsWith(
1088 serviceName.toUpperCase(Locale.ENGLISH))) {
1089 // We should skip the currentKey if it contains a
1090 // whitespace. The reason is: such an entry in the
1091 // provider property contains attributes for the
1092 // implementation of an algorithm. We are only interested
1093 // in entries which lead to the implementation
|
632 firstSearch = false;
633 }
634
635 if ((newCandidates != null) && !newCandidates.isEmpty()) {
636 // For each provider in the candidates set, if it
637 // isn't in the newCandidate set, we should remove
638 // it from the candidate set.
639 for (Iterator<Provider> cansIte = candidates.iterator();
640 cansIte.hasNext(); ) {
641 Provider prov = cansIte.next();
642 if (!newCandidates.contains(prov)) {
643 cansIte.remove();
644 }
645 }
646 } else {
647 candidates = null;
648 break;
649 }
650 }
651
652 if (candidates == null || candidates.isEmpty())
653 return null;
654
655 Object[] candidatesArray = candidates.toArray();
656 Provider[] result = new Provider[candidatesArray.length];
657
658 for (int i = 0; i < result.length; i++) {
659 result[i] = (Provider)candidatesArray[i];
660 }
661
662 return result;
663 }
664
665 // Map containing cached Spi Class objects of the specified type
666 private static final Map<String, Class<?>> spiMap =
667 new ConcurrentHashMap<>();
668
669 /**
670 * Return the Class object for the given engine type
671 * (e.g. "MessageDigest"). Works for Spis in the java.security package
672 * only.
988 if (attribute.equalsIgnoreCase("ImplementedIn")) {
989 return value.equalsIgnoreCase(prop);
990 }
991
992 return false;
993 }
994
995 static String[] getFilterComponents(String filterKey, String filterValue) {
996 int algIndex = filterKey.indexOf('.');
997
998 if (algIndex < 0) {
999 // There must be a dot in the filter, and the dot
1000 // shouldn't be at the beginning of this string.
1001 throw new InvalidParameterException("Invalid filter");
1002 }
1003
1004 String serviceName = filterKey.substring(0, algIndex);
1005 String algName = null;
1006 String attrName = null;
1007
1008 if (filterValue.isEmpty()) {
1009 // The filterValue is an empty string. So the filterKey
1010 // should be in the format of <crypto_service>.<algorithm_or_type>.
1011 algName = filterKey.substring(algIndex + 1).trim();
1012 if (algName.isEmpty()) {
1013 // There must be a algorithm or type name.
1014 throw new InvalidParameterException("Invalid filter");
1015 }
1016 } else {
1017 // The filterValue is a non-empty string. So the filterKey must be
1018 // in the format of
1019 // <crypto_service>.<algorithm_or_type> <attribute_name>
1020 int attrIndex = filterKey.indexOf(' ');
1021
1022 if (attrIndex == -1) {
1023 // There is no attribute name in the filter.
1024 throw new InvalidParameterException("Invalid filter");
1025 } else {
1026 attrName = filterKey.substring(attrIndex + 1).trim();
1027 if (attrName.isEmpty()) {
1028 // There is no attribute name in the filter.
1029 throw new InvalidParameterException("Invalid filter");
1030 }
1031 }
1032
1033 // There must be an algorithm name in the filter.
1034 if ((attrIndex < algIndex) ||
1035 (algIndex == attrIndex - 1)) {
1036 throw new InvalidParameterException("Invalid filter");
1037 } else {
1038 algName = filterKey.substring(algIndex + 1, attrIndex);
1039 }
1040 }
1041
1042 String[] result = new String[3];
1043 result[0] = serviceName;
1044 result[1] = algName;
1045 result[2] = attrName;
1046
1047 return result;
1053 * (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore). Returns
1054 * an empty Set if there is no provider that supports the
1055 * specified service or if serviceName is null. For a complete list
1056 * of Java cryptographic services, please see the
1057 * {@extLink security_guide_jca
1058 * Java Cryptography Architecture (JCA) Reference Guide}.
1059 * Note: the returned set is immutable.
1060 *
1061 * @param serviceName the name of the Java cryptographic
1062 * service (e.g., Signature, MessageDigest, Cipher, Mac, KeyStore).
1063 * Note: this parameter is case-insensitive.
1064 *
1065 * @return a Set of Strings containing the names of all available
1066 * algorithms or types for the specified Java cryptographic service
1067 * or an empty set if no provider supports the specified service.
1068 *
1069 * @since 1.4
1070 **/
1071 public static Set<String> getAlgorithms(String serviceName) {
1072
1073 if ((serviceName == null) || (serviceName.isEmpty()) ||
1074 (serviceName.endsWith("."))) {
1075 return Collections.emptySet();
1076 }
1077
1078 HashSet<String> result = new HashSet<>();
1079 Provider[] providers = Security.getProviders();
1080
1081 for (int i = 0; i < providers.length; i++) {
1082 // Check the keys for each provider.
1083 for (Enumeration<Object> e = providers[i].keys();
1084 e.hasMoreElements(); ) {
1085 String currentKey =
1086 ((String)e.nextElement()).toUpperCase(Locale.ENGLISH);
1087 if (currentKey.startsWith(
1088 serviceName.toUpperCase(Locale.ENGLISH))) {
1089 // We should skip the currentKey if it contains a
1090 // whitespace. The reason is: such an entry in the
1091 // provider property contains attributes for the
1092 // implementation of an algorithm. We are only interested
1093 // in entries which lead to the implementation
|