private void processModules(
     ServerProvisioning serverProvisioning,
     File outputDirectory,
     Set<String> filesProcessed,
     ArtifactFileResolver artifactFileResolver,
     File schemaOutputDirectory)
     throws IOException, XMLStreamException {
   // 1. gather the modules for each feature pack
   final Map<FeaturePack, List<FeaturePack.Module>> featurePackModulesMap = new HashMap<>();
   Set<ModuleIdentifier> moduleIdentifiers = new HashSet<>();
   for (ServerProvisioningFeaturePack provisioningFeaturePack :
       serverProvisioning.getFeaturePacks()) {
     getLog()
         .debugf(
             "Gathering modules for provisioning feature pack %s",
             provisioningFeaturePack.getFeaturePack().getFeaturePackFile());
     for (FeaturePack.Module module :
         provisioningFeaturePack
             .getModules(
                 artifactFileResolver, serverProvisioning.getDescription().isExcludeDependencies())
             .values()) {
       final ModuleIdentifier moduleIdentifier = module.getIdentifier();
       if (moduleIdentifiers.add(moduleIdentifier)) {
         getLog()
             .debugf(
                 "Adding module %s from feature pack %s",
                 moduleIdentifier, module.getFeaturePack().getFeaturePackFile());
         List<FeaturePack.Module> featurePackModules =
             featurePackModulesMap.get(module.getFeaturePack());
         if (featurePackModules == null) {
           featurePackModules = new ArrayList<>();
           featurePackModulesMap.put(module.getFeaturePack(), featurePackModules);
         }
         featurePackModules.add(module);
       } else {
         getLog()
             .debugf(
                 "Skipping %s from feature pack %s. A module with such identifier is already in the provisioning module set.",
                 moduleIdentifier, module.getFeaturePack().getFeaturePackFile());
       }
     }
     // we always need to resolve all subsystem templates, regardless of the value of
     // exclude-dependencies
     for (FeaturePack.Module module :
         provisioningFeaturePack.getModules(artifactFileResolver, false).values()) {
       for (ModuleParseResult.ArtifactName artifactName :
           module.getModuleParseResult().getArtifacts()) {
         String artifactCoords = artifactName.getArtifactCoords();
         String options = artifactName.getOptions();
         Artifact artifact =
             module.getFeaturePack().getArtifactResolver().getArtifact(artifactCoords);
         if (artifact == null) {
           throw new RuntimeException(
               "Could not resolve module resource artifact "
                   + artifactName
                   + " for feature pack "
                   + module.getFeaturePack().getFeaturePackFile());
         }
         File artifactFile = artifactFileResolver.getArtifactFile(artifact);
         // add all subsystem templates
         serverProvisioning
             .getConfig()
             .getInputStreamSources()
             .addAllSubsystemFileSourcesFromZipFile(artifactFile);
       }
     }
   }
   // 2. provision each feature pack modules
   for (Map.Entry<FeaturePack, List<FeaturePack.Module>> mapEntry :
       featurePackModulesMap.entrySet()) {
     FeaturePack featurePack = mapEntry.getKey();
     List<FeaturePack.Module> includedModules = mapEntry.getValue();
     processFeaturePackModules(
         featurePack,
         includedModules,
         serverProvisioning,
         outputDirectory,
         filesProcessed,
         artifactFileResolver,
         schemaOutputDirectory);
   }
 }