private void loadResourceModelSources() {
    Map<String, Exception> exceptions =
        Collections.synchronizedMap(new HashMap<String, Exception>());
    Set<String> validSources = new HashSet<>();
    // generate Configuration for file source
    if (projectConfig.hasProperty(PROJECT_RESOURCES_FILE_PROPERTY)) {
      try {
        final Properties config = createFileSourceConfiguration();
        logger.info("Source (project.resources.file): loading with properties: " + config);
        nodesSourceList.add(
            loadResourceModelSource("file", config, shouldCacheForType("file"), "file.file"));
        validSources.add("project.file");
      } catch (ExecutionServiceException e) {
        logger.error("Failed to load file resource model source: " + e.getMessage(), e);
        exceptions.put("project.file", e);
      }
    }
    if (projectConfig.hasProperty(PROJECT_RESOURCES_URL_PROPERTY)) {
      try {
        final Properties config = createURLSourceConfiguration();
        logger.info("Source (project.resources.url): loading with properties: " + config);
        nodesSourceList.add(
            loadResourceModelSource("url", config, shouldCacheForType("url"), "file.url"));
        validSources.add("project.url");
      } catch (ExecutionServiceException e) {
        logger.error("Failed to load file resource model source: " + e.getMessage(), e);
        exceptions.put("project.url", e);
      }
    }

    final List<Map<String, Object>> list = listResourceModelConfigurations();
    int i = 1;
    for (final Map<String, Object> map : list) {
      final String providerType = (String) map.get("type");
      final Properties props = (Properties) map.get("props");

      logger.info("Source #" + i + " (" + providerType + "): loading with properties: " + props);
      try {
        nodesSourceList.add(
            loadResourceModelSource(
                providerType, props, shouldCacheForType(providerType), i + ".source"));
        validSources.add(i + ".source");
      } catch (ExecutionServiceException e) {
        logger.error(
            "Failed loading resource model source #" + i + ", skipping: " + e.getMessage(), e);
        exceptions.put(i + ".source", e);
      }
      i++;
    }
    synchronized (nodesSourceExceptions) {
      nodesSourceExceptions.putAll(exceptions);
      for (String validSource : validSources) {
        nodesSourceExceptions.remove(validSource);
      }
    }

    Date configLastModifiedTime = projectConfig.getConfigLastModifiedTime();
    nodesSourcesLastReload = configLastModifiedTime != null ? configLastModifiedTime.getTime() : -1;
  }
 /**
  * Create a {@link NodeSetMerge} based on project configuration, it defaults to merge all node
  * attributes unless "project.resources.mergeNodeAttributes" is false
  *
  * @return a NodeSetMerge
  */
 private NodeSetMerge getNodeSetMerge() {
   if (projectConfig.hasProperty(PROJECT_RESOURCES_MERGE_NODE_ATTRIBUTES)
       && "false".equals(projectConfig.getProperty(PROJECT_RESOURCES_MERGE_NODE_ATTRIBUTES))) {
     return new AdditiveListNodeSet();
   }
   return new MergedAttributesNodeSet();
 }
 private Properties createFileSourceConfiguration() {
   String format = null;
   if (projectConfig.hasProperty(PROJECT_RESOURCES_FILEFORMAT_PROPERTY)) {
     format = projectConfig.getProperty(PROJECT_RESOURCES_FILEFORMAT_PROPERTY);
   }
   return generateFileSourceConfigurationProperties(
       projectConfig.getProperty(PROJECT_RESOURCES_FILE_PROPERTY), format, true, true);
 }
  /**
   * Return true in these cases: 1. project.properties allows URL and framework.properties allows
   * URL. 2. project.properties allows URL and no regexes are set in framework.properties 3.
   * project.properties no regexes are set, and framework.properites allows URL.
   */
  boolean isAllowedProviderURL(final String providerURL) {
    // whitelist the configured providerURL
    if (projectConfig.hasProperty(PROJECT_RESOURCES_URL_PROPERTY)
        && projectConfig.getProperty(PROJECT_RESOURCES_URL_PROPERTY).equals(providerURL)) {
      return true;
    }
    // check regex properties for project props
    int i = 0;
    boolean projpass = false;
    boolean setproj = false;
    while (projectConfig.hasProperty(PROJECT_RESOURCES_ALLOWED_URL_PREFIX + i)) {
      setproj = true;
      final String regex = projectConfig.getProperty(PROJECT_RESOURCES_ALLOWED_URL_PREFIX + i);
      final Pattern pat = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
      final Matcher matcher = pat.matcher(providerURL);
      if (matcher.matches()) {
        logger.debug(
            "ProviderURL allowed by project property \"project.resources.allowedURL."
                + i
                + "\": "
                + regex);
        projpass = true;
        break;
      }
      i++;
    }
    if (!projpass && setproj) {
      // was checked but failed match
      return false;
    }
    // check framework props
    i = 0;

    final boolean setframework =
        projectConfig.hasProperty(FRAMEWORK_RESOURCES_ALLOWED_URL_PREFIX + i);
    if (!setframework && projpass) {
      // unset in framework.props, allowed by project.props
      return true;
    }
    if (!setframework && !setproj) {
      // unset in both
      return false;
    }
    while (projectConfig.hasProperty(FRAMEWORK_RESOURCES_ALLOWED_URL_PREFIX + i)) {
      final String regex = projectConfig.getProperty(FRAMEWORK_RESOURCES_ALLOWED_URL_PREFIX + i);
      final Pattern pat = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
      final Matcher matcher = pat.matcher(providerURL);
      if (matcher.matches()) {
        logger.debug(
            "ProviderURL allowed by framework property \"framework.resources.allowedURL."
                + i
                + "\": "
                + regex);
        // allowed by framework.props, and unset or allowed by project.props,
        return true;
      }
      i++;
    }
    if (projpass) {
      logger.warn(
          "providerURL was allowed by project.properties, but is not allowed by framework.properties: "
              + providerURL);
    }
    return false;
  }
 /**
  * Return true if the resources file should be pulled from the server If he node is the server and
  * workbench integration is enabled then the file should not be updated.
  */
 private boolean shouldUpdateNodesResourceFile() {
   return projectConfig.hasProperty(PROJECT_RESOURCES_URL_PROPERTY);
 }