// Parse a single line from the given configuration file, adding the name
 // on the line to the names list.
 //
 private int parseLine(Class<?> service, URL u, BufferedReader r, int lc, List<String> names)
     throws IOException, ServiceConfigurationError {
   String ln = r.readLine();
   if (ln == null) {
     return -1;
   }
   int ci = ln.indexOf('#');
   if (ci >= 0) ln = ln.substring(0, ci);
   ln = ln.trim();
   int n = ln.length();
   if (n != 0) {
     if ((ln.indexOf(' ') >= 0) || (ln.indexOf('\t') >= 0))
       fail(service, u, lc, "Illegal configuration-file syntax");
     int cp = ln.codePointAt(0);
     if (!Character.isJavaIdentifierStart(cp))
       fail(service, u, lc, "Illegal provider-class name: " + ln);
     for (int i = Character.charCount(cp); i < n; i += Character.charCount(cp)) {
       cp = ln.codePointAt(i);
       if (!Character.isJavaIdentifierPart(cp) && (cp != '.'))
         fail(service, u, lc, "Illegal provider-class name: " + ln);
     }
     if (!providers.containsKey(ln) && !names.contains(ln)) names.add(ln);
   }
   return lc + 1;
 }
 // Parse the content of the given URL as a provider-configuration file.
 //
 // @param  service
 //         The service type for which providers are being sought;
 //         used to construct error detail strings
 //
 // @param  u
 //         The URL naming the configuration file to be parsed
 //
 // @return A (possibly empty) iterator that will yield the provider-class
 //         names in the given configuration file that are not yet members
 //         of the returned set
 //
 // @throws ServiceConfigurationError
 //         If an I/O error occurs while reading from the given URL, or
 //         if a configuration-file format error is detected
 //
 private Iterator<String> parse(Class<?> service, URL u) throws ServiceConfigurationError {
   InputStream in = null;
   ArrayList<String> names = new ArrayList<>();
   try {
     // The problem is that by default, streams opened with
     // u.openInputStream use a cached reference to a JarFile, which
     // is separate from the reference used by URLClassLoader, and
     // which is not closed by URLClassLoader.close().
     // The workaround is to disable caching for this specific jar file,
     // so that the reference to the jar file can be closed when the
     // file has been read.
     // Original code:
     // in = u.openStream();
     // Workaround ...
     URLConnection uc = u.openConnection();
     uc.setUseCaches(false);
     in = uc.getInputStream();
     // ... end of workaround.
     try (BufferedReader r = new BufferedReader(new InputStreamReader(in, "utf-8"))) {
       int lc = 1;
       while ((lc = parseLine(service, u, r, lc, names)) >= 0) ;
     }
   } catch (IOException x) {
     fail(service, "Error reading configuration file", x);
   } finally {
     try {
       if (in != null) in.close();
     } catch (IOException y) {
       fail(service, "Error closing configuration file", y);
     }
   }
   return names.iterator();
 }
 private static void fail(Class<?> service, URL u, int line, String msg)
     throws ServiceConfigurationError {
   fail(service, u + ":" + line + ": " + msg);
 }