docs: static void generateProjectPropertiesFile(
              final String name,
              final File destfile,
              final boolean overwrite,
              final Properties properties,
              final boolean merge,
              final Set<String> removePrefixes,
              boolean addDefaultProps
      )
      {
          if (destfile.exists() && !overwrite) {
              return;
          }
          final Properties newProps = new Properties();
          newProps.setProperty("project.name", name);
  
          //TODO: improve default configuration generation
          if (addDefaultProps) {
              if (null == properties || !properties.containsKey("resources.source.1.type")) {
                  //add default file source
                  newProps.setProperty("resources.source.1.type", "local");
              }
              if (null == properties || !properties.containsKey("service.NodeExecutor.default.provider")) {
                  newProps.setProperty("service.NodeExecutor.default.provider", "jsch-ssh");
              }
              if (null == properties || !properties.containsKey("service.FileCopier.default.provider")) {
                  newProps.setProperty("service.FileCopier.default.provider", "jsch-scp");
              }
              if (null == properties || !properties.containsKey("project.ssh-keypath")) {
                  newProps.setProperty("project.ssh-keypath", new File(
                          System.getProperty("user.home"),
                          ".ssh/id_rsa"
                  ).getAbsolutePath());
              }
              if (null == properties || !properties.containsKey("project.ssh-authentication")) {
                  newProps.setProperty("project.ssh-authentication", "privateKey");
              }
          }
          if (merge) {
              final Properties orig = new Properties();
  
              if (destfile.exists()) {
                  try {
                      final FileInputStream fileInputStream = new FileInputStream(destfile);
                      try {
                          orig.load(fileInputStream);
                      } finally {
                          fileInputStream.close();
                      }
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
              }
              //add all original properties that are not in the incoming  properties, and are not
              //matched by one of the remove prefixes
              entry:
              for (final Object o : orig.entrySet()) {
                  Map.Entry entry = (Map.Entry) o;
                  //determine if
                  final String key = (String) entry.getKey();
                  if (null != removePrefixes) {
                      for (final String replacePrefix : removePrefixes) {
                          if (key.startsWith(replacePrefix)) {
                              //skip this key
                              continue entry;
                          }
                      }
                  }
                  newProps.put(entry.getKey(), entry.getValue());
              }
          }
          //overwrite original with the input properties
          if (null != properties) {
              newProps.putAll(properties);
          }
  
          try {
              if(!destfile.getParentFile().exists()){
                  destfile.getParentFile().mkdirs();
              }
              final FileOutputStream fileOutputStream = new FileOutputStream(destfile);
              try {
                  newProps.store(fileOutputStream, "Project " + name + " configuration, generated");
              } finally {
                  fileOutputStream.close();
              }
          } catch (IOException e) {
              e.printStackTrace();
          }
  
          logger.debug("generated project.properties: " + destfile.getAbsolutePath());
      }