/*
   * Read multiple resource files from the classpaths given the file name.
   * This method is designed as package visibility to improve performance when
   * called by anonymous inner classes.
   *
   * @param name - the name of the resource file @param existingProps -
   * existing properties, cannot be null @param filter - to filter properties
   */
  static Hashtable<Object, Object> readMultipleResourceFiles(
      final String name, final Hashtable<Object, Object> existingProps, ClassLoader cl)
      throws NamingException {

    if (null == cl) {
      cl = ClassLoader.getSystemClassLoader();
    }

    Enumeration<URL> e = null;
    try {
      // Load all resource files
      e = cl.getResources(name);
    } catch (final IOException ex) {
      // Unexpected ClassLoader exception
      // jndi.23=Failed to load JNDI resource files.
      final ConfigurationException newEx =
          new ConfigurationException(Messages.getString("jndi.23")); // $NON-NLS-1$
      newEx.setRootCause(ex);
      throw newEx;
    }

    // Read all the loaded properties and merge
    URL url = null;
    InputStream is = null;
    final Properties p = new Properties();
    while (e.hasMoreElements()) {
      url = e.nextElement();
      try {
        if (null != (is = url.openStream())) {
          p.load(is);
          mergeEnvironment(p, existingProps, true);
          p.clear();
        }
      } catch (final IOException ex) {
        // Can't read this resource file
        // jndi.24=Failed to read JNDI resource files.
        final ConfigurationException newEx =
            new ConfigurationException(Messages.getString("jndi.24")); // $NON-NLS-1$
        newEx.setRootCause(ex);
        throw newEx;
      } finally {
        try {
          if (null != is) {
            is.close();
          }
        } catch (final IOException ex) {
          // Ignore closing exception
        } finally {
          is = null;
        }
      }
    }
    return existingProps;
  }
  /*
   * Read the properties file "java.home"/lib/jndi.properties. Pay attention
   * to the privileged code for accessing this external resource file. This is
   * required if JNDI is run in Applet or other applications which only have
   * limited permissions to access certain resources.
   *
   * @param existingProps - existing properties, cannot be null.
   */
  public static Hashtable<Object, Object> readLibraryResourceFile(
      final Hashtable<Object, Object> existingProps) throws NamingException {
    final String sep = System.getProperty("file.separator"); // $NON-NLS-1$

    String resPath = null;
    // Construct the full filename of "java.home"/lib/jndi.properties
    resPath =
        AccessController.doPrivileged(
            new PrivilegedAction<String>() {
              @Override
              public String run() {
                return System.getProperty("java.home"); // $NON-NLS-1$
              }
            });

    if (!resPath.endsWith(sep)) {
      resPath += sep;
    }
    resPath += "lib" + sep + APPLICATION_RESOURCE_FILE; // $NON-NLS-1$

    // Try to read this properties if it exists
    InputStream is = null;
    final File resFile = new File(resPath);
    final Properties p = new Properties();
    // Use privileged code to determine whether the file exists
    final boolean resFileExists =
        AccessController.doPrivileged(
                new PrivilegedAction<Boolean>() {
                  @Override
                  public Boolean run() {
                    return Boolean.valueOf(resFile.exists());
                  }
                })
            .booleanValue();
    if (resFileExists) {
      try {
        // Use privileged code to read the file
        is =
            AccessController.doPrivileged(
                new PrivilegedExceptionAction<FileInputStream>() {
                  @Override
                  public FileInputStream run() throws IOException {
                    final FileInputStream localInputStream = new FileInputStream(resFile);
                    p.load(localInputStream);
                    return localInputStream;
                  }
                });
        mergeEnvironment(p, existingProps, true);
      } catch (final PrivilegedActionException e) {
        // Can't read "java.home"/lib/jndi.properties
        // jndi.25=Failed to read JNDI resource files in java home
        // library.
        final ConfigurationException newEx =
            new ConfigurationException(Messages.getString("jndi.25")); // $NON-NLS-1$
        newEx.setRootCause(e.getException());
        throw newEx;
      } finally {
        try {
          if (null != is) {
            is.close();
          }
        } catch (final IOException ex) {
          // Ignore closing exception
        }
      }
    }
    return existingProps;
  }