1005 private final class LazyClassPathLookupIterator<T> |
1005 private final class LazyClassPathLookupIterator<T> |
1006 implements Iterator<Provider<T>> |
1006 implements Iterator<Provider<T>> |
1007 { |
1007 { |
1008 static final String PREFIX = "META-INF/services/"; |
1008 static final String PREFIX = "META-INF/services/"; |
1009 |
1009 |
|
1010 Set<String> providerNames = new HashSet<>(); // to avoid duplicates |
1010 Enumeration<URL> configs; |
1011 Enumeration<URL> configs; |
1011 Iterator<String> pending; |
1012 Iterator<String> pending; |
1012 Class<?> nextClass; |
1013 Class<?> nextClass; |
1013 String nextErrorMessage; // when hasNext fails with CNFE |
1014 String nextErrorMessage; // when hasNext fails with CNFE |
1014 |
1015 |
1015 LazyClassPathLookupIterator() { } |
1016 LazyClassPathLookupIterator() { } |
1016 |
1017 |
1017 /** |
1018 /** |
1018 * Parse a single line from the given configuration file, adding the |
1019 * Parse a single line from the given configuration file, adding the |
1019 * name on the line to the names list. |
1020 * name on the line to set of names if not already seen. |
1020 */ |
1021 */ |
1021 private int parseLine(URL u, BufferedReader r, int lc, Set<String> names) |
1022 private int parseLine(URL u, BufferedReader r, int lc, Set<String> names) |
1022 throws IOException |
1023 throws IOException |
1023 { |
1024 { |
1024 String ln = r.readLine(); |
1025 String ln = r.readLine(); |
1039 for (int i = start; i < n; i += Character.charCount(cp)) { |
1040 for (int i = start; i < n; i += Character.charCount(cp)) { |
1040 cp = ln.codePointAt(i); |
1041 cp = ln.codePointAt(i); |
1041 if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) |
1042 if (!Character.isJavaIdentifierPart(cp) && (cp != '.')) |
1042 fail(service, u, lc, "Illegal provider-class name: " + ln); |
1043 fail(service, u, lc, "Illegal provider-class name: " + ln); |
1043 } |
1044 } |
1044 names.add(ln); |
1045 if (providerNames.add(ln)) { |
|
1046 names.add(ln); |
|
1047 } |
1045 } |
1048 } |
1046 return lc + 1; |
1049 return lc + 1; |
1047 } |
1050 } |
1048 |
1051 |
1049 /** |
1052 /** |
1070 private boolean hasNextService() { |
1073 private boolean hasNextService() { |
1071 if (nextClass != null || nextErrorMessage != null) { |
1074 if (nextClass != null || nextErrorMessage != null) { |
1072 return true; |
1075 return true; |
1073 } |
1076 } |
1074 |
1077 |
1075 Class<?> clazz = null; |
1078 Class<?> clazz; |
1076 do { |
1079 do { |
1077 if (configs == null) { |
1080 if (configs == null) { |
1078 try { |
1081 try { |
1079 String fullName = PREFIX + service.getName(); |
1082 String fullName = PREFIX + service.getName(); |
1080 if (loader == null) { |
1083 if (loader == null) { |