private Properties createURLSourceConfiguration() {
    final URLResourceModelSource.Configuration build = URLResourceModelSource.Configuration.build();
    build.url(projectConfig.getProperty(PROJECT_RESOURCES_URL_PROPERTY));
    build.project(projectConfig.getName());

    return build.getProperties();
  }
 /**
  * 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 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;
  }
 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);
 }
 private File getResourceModelSourceFileCacheForType(String ident) {
   String varDir = projectConfig.getProperty("framework.var.dir");
   File file =
       new File(
           varDir, "resourceModelSourceCache/" + projectConfig.getName() + "/" + ident + ".xml");
   if (!file.getParentFile().exists() && !file.getParentFile().mkdirs()) {
     logger.warn("Failed to create cache dirs for source file cache");
   }
   return file;
 }
 private synchronized Collection<ResourceModelSource> getResourceModelSources() {
   // determine if sources need to be reloaded
   final long lastMod =
       projectConfig.getConfigLastModifiedTime() != null
           ? projectConfig.getConfigLastModifiedTime().getTime()
           : 0;
   if (lastMod > nodesSourcesLastReload) {
     nodesSourceList = new ArrayList<>();
     loadResourceModelSources();
   }
   return nodesSourceList;
 }
 /**
  * list the configurations of resource model providers.
  *
  * @return a list of maps containing:
  *     <ul>
  *       <li>type - provider type name
  *       <li>props - configuration properties
  *     </ul>
  */
 @Override
 public synchronized List<Map<String, Object>> listResourceModelConfigurations() {
   Map propertiesMap = projectConfig.getProperties();
   Properties properties = new Properties();
   properties.putAll(propertiesMap);
   return listResourceModelConfigurations(properties);
 }
  /**
   * @param logging
   * @param origin origin source
   * @param ident unique identity for this cached source, used in filename
   * @param descr description of the source, used in logging
   * @param logging if true, log cache access
   * @return new source
   */
  public ResourceModelSource createCachingSource(
      ResourceModelSource origin,
      String ident,
      String descr,
      SourceFactory.CacheType type,
      final boolean logging) {
    final File file = getResourceModelSourceFileCacheForType(ident);
    final ResourceModelSourceService nodesSourceService = getResourceModelSourceService();
    final ResourceFormatGeneratorService resourceFormatGeneratorService =
        getResourceFormatGeneratorService();
    final Properties fileSourceConfig =
        generateFileSourceConfigurationProperties(
            file.getAbsolutePath(), ResourceXMLFormatGenerator.SERVICE_PROVIDER_TYPE, false, false);
    try {
      ResourceModelSource fileSource =
          nodesSourceService.getSourceForConfiguration("file", fileSourceConfig);

      ResourceFormatGenerator generatorForFormat =
          resourceFormatGeneratorService.getGeneratorForFormat(
              ResourceXMLFormatGenerator.SERVICE_PROVIDER_TYPE);

      String ident1 =
          "[ResourceModelSource: " + descr + ", project: " + projectConfig.getName() + "]";
      StoreExceptionHandler handler = new StoreExceptionHandler(ident);
      ResourceModelSourceCache cache =
          new FileResourceModelSourceCache(file, generatorForFormat, fileSource);
      if (logging) {
        cache = new LoggingResourceModelSourceCache(cache, ident1);
      }
      return SourceFactory.cachedSource(origin, ident1, handler, cache, type);
    } catch (UnsupportedFormatException | ExecutionServiceException e) {
      e.printStackTrace();
    }
    return null;
  }
 /**
  * Conditionally update the nodes resources file if a URL source is defined for it and return true
  * if the update process was invoked and succeeded
  *
  * @param nodesResourcesFilePath destination file path
  * @return true if the update succeeded, false if it was not performed
  * @throws UpdateUtils.UpdateException if an error occurs while trying to update the resources
  *     file
  */
 @Override
 public boolean updateNodesResourceFile(final String nodesResourcesFilePath)
     throws UpdateUtils.UpdateException {
   if (shouldUpdateNodesResourceFile()) {
     updateNodesResourceFileFromUrl(
         projectConfig.getProperty(PROJECT_RESOURCES_URL_PROPERTY),
         null,
         null,
         nodesResourcesFilePath);
     return true;
   }
   return false;
 }
  private Properties generateFileSourceConfigurationProperties(
      String filepath, String format, boolean generate, boolean includeServerNode) {
    final FileResourceModelSource.Configuration build =
        FileResourceModelSource.Configuration.build();
    build.file(filepath);
    if (null != format) {
      build.format(format);
    }
    build.project(projectConfig.getName());
    build.generateFileAutomatically(generate);
    build.includeServerNode(includeServerNode);

    return build.getProperties();
  }
  private ResourceModelSource loadResourceModelSource(
      String type, Properties configuration, boolean useCache, String ident)
      throws ExecutionServiceException {

    final ResourceModelSourceService nodesSourceService = getResourceModelSourceService();
    configuration.put("project", projectConfig.getName());
    ResourceModelSource sourceForConfiguration =
        nodesSourceService.getSourceForConfiguration(type, configuration);

    if (useCache) {
      ResourceModelSourceFactory provider = nodesSourceService.providerOfType(type);
      String name = ident;
      if (provider instanceof Describable) {
        Describable desc = (Describable) provider;
        Description description = desc.getDescription();
        name = ident + " (" + description.getTitle() + ")";
      }
      return createCachingSource(sourceForConfiguration, ident, name);
    } else {
      return sourceForConfiguration;
    }
  }
  /**
   * 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);
 }