private void processFeaturePackCopyArtifacts(
     FeaturePack featurePack,
     File outputDirectory,
     Set<String> filesProcessed,
     ArtifactFileResolver artifactFileResolver,
     File schemaOutputDirectory,
     boolean excludeDependencies)
     throws IOException {
   processCopyArtifacts(
       featurePack.getDescription().getCopyArtifacts(),
       featurePack.getArtifactResolver(),
       outputDirectory,
       filesProcessed,
       artifactFileResolver,
       schemaOutputDirectory);
   if (!excludeDependencies) {
     for (FeaturePack dependency : featurePack.getDependencies()) {
       processFeaturePackCopyArtifacts(
           dependency,
           outputDirectory,
           filesProcessed,
           artifactFileResolver,
           schemaOutputDirectory,
           excludeDependencies);
     }
   }
 }
  private void processFeaturePackFilePermissions(
      FeaturePack featurePack, File outputDirectory, boolean excludeDependencies)
      throws IOException {
    final Path baseDir = Paths.get(outputDirectory.getAbsolutePath());
    final List<FilePermission> filePermissions = featurePack.getDescription().getFilePermissions();
    Files.walkFileTree(
        baseDir,
        new SimpleFileVisitor<Path>() {
          @Override
          public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
              throws IOException {
            String relative = baseDir.relativize(dir).toString();
            if (!OS_WINDOWS) {
              for (FilePermission perm : filePermissions) {
                if (perm.includeFile(relative)) {
                  Files.setPosixFilePermissions(dir, perm.getPermission());
                  continue;
                }
              }
            }
            return FileVisitResult.CONTINUE;
          }

          @Override
          public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
              throws IOException {
            String relative = baseDir.relativize(file).toString();
            if (!OS_WINDOWS) {
              for (FilePermission perm : filePermissions) {
                if (perm.includeFile(relative)) {
                  Files.setPosixFilePermissions(file, perm.getPermission());
                  continue;
                }
              }
            }
            return FileVisitResult.CONTINUE;
          }
        });
    if (!excludeDependencies) {
      for (FeaturePack dependency : featurePack.getDependencies()) {
        processFeaturePackFilePermissions(dependency, outputDirectory, excludeDependencies);
      }
    }
  }
 private void processFeaturePackConfig(
     ServerProvisioningFeaturePack provisioningFeaturePack,
     ServerProvisioning.Config provisioningConfig)
     throws IOException, XMLStreamException {
   FeaturePack featurePack = provisioningFeaturePack.getFeaturePack();
   getLog()
       .debug(
           "Processing provisioning feature pack "
               + featurePack.getFeaturePackFile()
               + " configs");
   try (ZipFile zipFile = new ZipFile(featurePack.getFeaturePackFile())) {
     for (ServerProvisioningFeaturePack.ConfigFile serverProvisioningFeaturePackConfigFile :
         provisioningFeaturePack.getDomainConfigFiles()) {
       processFeaturePackConfigFile(
           serverProvisioningFeaturePackConfigFile,
           zipFile,
           provisioningFeaturePack,
           provisioningConfig.getDomainConfigFiles());
     }
     for (ServerProvisioningFeaturePack.ConfigFile serverProvisioningFeaturePackConfigFile :
         provisioningFeaturePack.getStandaloneConfigFiles()) {
       processFeaturePackConfigFile(
           serverProvisioningFeaturePackConfigFile,
           zipFile,
           provisioningFeaturePack,
           provisioningConfig.getStandaloneConfigFiles());
     }
     for (ServerProvisioningFeaturePack.ConfigFile serverProvisioningFeaturePackConfigFile :
         provisioningFeaturePack.getHostConfigFiles()) {
       processFeaturePackConfigFile(
           serverProvisioningFeaturePackConfigFile,
           zipFile,
           provisioningFeaturePack,
           provisioningConfig.getHostConfigFiles());
     }
   }
 }
 private void processFeaturePackContents(
     FeaturePack featurePack,
     ServerProvisioningDescription.FeaturePack.ContentFilters contentFilters,
     File outputDirectory,
     Set<String> filesProcessed,
     boolean excludeDependencies)
     throws IOException {
   final int fileNameWithoutContentsStart = Locations.CONTENT.length() + 1;
   try (JarFile jar = new JarFile(featurePack.getFeaturePackFile())) {
     for (String contentFile : featurePack.getContentFiles()) {
       final String outputFile = contentFile.substring(fileNameWithoutContentsStart);
       boolean include = true;
       if (contentFilters != null) {
         include = contentFilters.isInclude();
         for (FileFilter contentFilter : contentFilters.getFilters()) {
           if (contentFilter.matches(outputFile) && !contentFilter.isInclude()) {
             include = false;
             break;
           }
         }
       }
       if (!include) {
         getLog()
             .debugf(
                 "Skipping feature pack %s filtered content file %s",
                 featurePack.getFeaturePackFile(), outputFile);
         continue;
       }
       if (!filesProcessed.add(outputFile)) {
         getLog()
             .debugf(
                 "Skipping already processed feature pack %s content file %s",
                 featurePack.getFeaturePackFile(), outputFile);
         continue;
       }
       getLog()
           .debugf(
               "Adding feature pack %s content file %s",
               featurePack.getFeaturePackFile(), outputFile);
       FileUtils.extractFile(jar, contentFile, new java.io.File(outputDirectory, outputFile));
     }
   }
   if (!excludeDependencies) {
     for (FeaturePack dependency : featurePack.getDependencies()) {
       processFeaturePackContents(
           dependency, contentFilters, outputDirectory, filesProcessed, excludeDependencies);
     }
   }
 }
  private void processFeaturePackModules(
      FeaturePack featurePack,
      List<FeaturePack.Module> includedModules,
      ServerProvisioning serverProvisioning,
      File outputDirectory,
      Set<String> filesProcessed,
      ArtifactFileResolver artifactFileResolver,
      File schemaOutputDirectory)
      throws IOException {
    final boolean thinServer = !serverProvisioning.getDescription().isCopyModuleArtifacts();
    // create the module's artifact property replacer
    final BuildPropertyReplacer buildPropertyReplacer =
        thinServer
            ? new BuildPropertyReplacer(
                new ModuleArtifactPropertyResolver(featurePack.getArtifactResolver()))
            : null;
    // process each module file
    try (JarFile jar = new JarFile(featurePack.getFeaturePackFile())) {
      for (FeaturePack.Module module : includedModules) {
        // process the module file
        final String jarEntryName = module.getModuleFile();
        filesProcessed.add(jarEntryName);
        File targetFile = new File(outputDirectory, jarEntryName);
        // ensure parent dirs exist
        targetFile.getParentFile().mkdirs();
        // extract the module file
        FileUtils.extractFile(jar, jarEntryName, targetFile);
        // read module xml to string for content update
        String moduleXmlContents = FileUtils.readFile(targetFile);
        // parse the module xml
        ModuleParseResult result = module.getModuleParseResult();
        // process module artifacts
        for (ModuleParseResult.ArtifactName artifactName : result.getArtifacts()) {
          String artifactCoords = artifactName.getArtifactCoords();
          String options = artifactName.getOptions();
          boolean jandex = false;
          if (options != null) {
            jandex =
                options.contains(
                    "jandex"); // todo: eventually we may need options to have a proper query string
                               // type syntax
            moduleXmlContents =
                moduleXmlContents.replace(
                    artifactName.toString(),
                    artifactCoords); // todo: all these replace calls are a bit yuck, we may need
                                     // proper solution if this gets more complex
          }
          Artifact artifact = featurePack.getArtifactResolver().getArtifact(artifactCoords);
          if (artifact == null) {
            throw new RuntimeException(
                "Could not resolve module resource artifact "
                    + artifactName
                    + " for feature pack "
                    + featurePack.getFeaturePackFile());
          }
          try {
            // process the module artifact
            File artifactFile = artifactFileResolver.getArtifactFile(artifact);
            // extract schemas if needed
            extractSchema(schemaOutputDirectory, artifact, artifactFile);
            if (jandex) {
              String baseName =
                  artifactFile.getName().substring(0, artifactFile.getName().lastIndexOf("."));
              String extension =
                  artifactFile.getName().substring(artifactFile.getName().lastIndexOf("."));
              File target = new File(targetFile.getParent(), baseName + "-jandex" + extension);
              JandexIndexer.createIndex(artifactFile, new FileOutputStream(target));
              moduleXmlContents =
                  moduleXmlContents.replaceAll(
                      "(\\s*)<artifact\\s+name=\"\\$\\{" + artifactCoords + "\\}\"\\s*/>",
                      "$1<artifact name=\"\\${"
                          + artifactCoords
                          + "}\" />$1<resource-root path=\""
                          + target.getName()
                          + "\"/>");
              // it's also possible that this is an element with nested content
              // this regex involves a good deal of backtracking but it seems to work
              moduleXmlContents =
                  Pattern.compile(
                          "(\\s*)<artifact\\s+name=\"\\$\\{"
                              + artifactCoords
                              + "\\}\"\\s*>(.*)</artifact>",
                          Pattern.DOTALL)
                      .matcher(moduleXmlContents)
                      .replaceAll(
                          "$1<artifact name=\"\\${"
                              + artifactCoords
                              + "}\">$2</artifact>$1<resource-root path=\""
                              + target.getName()
                              + "\">$2</resource-root>");
            }
            if (!thinServer) {
              // copy the artifact
              String artifactFileName = artifactFile.getName();
              FileUtils.copyFile(artifactFile, new File(targetFile.getParent(), artifactFileName));
              // update module xml content
              moduleXmlContents =
                  moduleXmlContents.replaceAll(
                      "<artifact\\s+name=\"\\$\\{" + artifactCoords + "\\}\"\\s*/>",
                      "<resource-root path=\"" + artifactFileName + "\"/>");
              // it's also possible that this is an element with nested content
              // this regex involves a good deal of backtracking but it seems to work
              moduleXmlContents =
                  Pattern.compile(
                          "<artifact\\s+name=\"\\$\\{"
                              + artifactCoords
                              + "\\}\"\\s*>(.*)</artifact>",
                          Pattern.DOTALL)
                      .matcher(moduleXmlContents)
                      .replaceAll(
                          "<resource-root path=\"" + artifactFileName + "\">$1</resource-root>");
            }
          } catch (Throwable t) {
            throw new RuntimeException("Could not extract resources from " + artifactName, t);
          }
        }
        if (thinServer) {
          // replace artifact coords properties with the ones expected by jboss-modules
          moduleXmlContents = buildPropertyReplacer.replaceProperties(moduleXmlContents);
        }
        // write updated module xml content
        FileUtils.copyFile(
            new ByteArrayInputStream(moduleXmlContents.getBytes("UTF-8")), targetFile);

        // extract all other files in the module dir
        for (String moduleDirFile : module.getModuleDirFiles()) {
          filesProcessed.add(moduleDirFile);
          FileUtils.extractFile(jar, moduleDirFile, new File(outputDirectory, moduleDirFile));
        }
      }
    } catch (Throwable e) {
      throw new RuntimeException(
          "Failed to process feature pack " + featurePack.getFeaturePackFile() + " modules", e);
    }
  }