public static ApplicationConfiguration readConfiguration(final String... resources) {
    if (resources == null) return new ApplicationConfiguration(ImmutableMap.of());

    final HashMap<String, String> result = new HashMap<>();

    for (String resource : resources) {

      if (StringTools.isNullOrEmpty(resource)) continue;

      // Read anything from an external config file or resource
      if (FileTools.fileExistsAndCanRead(resource)) {
        mergeConfigMaps(readConfigFileLines(resource), result);
      } else {
        mergeConfigMaps(ResourceTools.readResourceTextFileAsMap(resource), result);
      }
    }

    // Check for system properties/envs for overrides
    // for the known configuration options and apply them
    // as overrides

    final Map<String, String> environmentMatches =
        MapTools.intersectKeysCaseInsensitive(result, System.getenv());

    for (Map.Entry<String, String> matchEntry : environmentMatches.entrySet()) {
      final String envOverride = System.getenv().get(matchEntry.getValue());

      if (!StringTools.isNullOrEmpty(envOverride)) {
        result.put(matchEntry.getKey(), envOverride);
      }
    }

    // Ultimately - command-line properties override everything

    final Map<String, Object> propertiesMatches =
        MapTools.intersectKeys(
            result,
            System.getProperties(),
            String::toLowerCase,
            key -> {
              if (key instanceof String) {
                return ((String) key).toLowerCase();
              } else {
                // Do not support non-string matching
                return UUID.randomUUID().toString();
              }
            });

    for (Map.Entry<String, Object> matchEntry : propertiesMatches.entrySet()) {
      final Object propertiesOverride = System.getProperties().get(matchEntry.getValue());

      if (propertiesOverride instanceof String
          && !StringTools.isNullOrEmpty((String) propertiesOverride)) {
        result.put(matchEntry.getKey(), (String) propertiesOverride);
      }
    }

    return new ApplicationConfiguration(ImmutableMap.copyOf(result));
  }
  private static Map<String, String> readConfigFileLines(final String configFile) {
    if (StringTools.isNullOrEmpty(configFile) || !FileTools.fileExistsAndCanRead(configFile))
      return ImmutableMap.of();

    try {
      LogTools.info("Reading config values from file {0}", configFile);

      return StringTools.convertStringsToMap(
          Files.readLines(new File(configFile), Charset.defaultCharset())
              .stream()
              .filter(line -> !line.trim().startsWith("#")) // remove comments
              .collect(Collectors.toList()),
          CharMatcher.is('='),
          false);

    } catch (IOException e) {
      throw Throwables.propagate(e);
    }
  }