protected void addNonArchiveDependency(
      final Artifact depArtifact,
      final MavenProject depProject,
      final DependencySet dependencySet,
      final Archiver archiver,
      final AssemblerConfigurationSource configSource)
      throws AssemblyFormattingException, ArchiveCreationException {
    final File source = depArtifact.getFile();

    String outputDirectory = dependencySet.getOutputDirectory();

    outputDirectory =
        AssemblyFormatUtils.getOutputDirectory(
            outputDirectory,
            configSource.getProject(),
            moduleProject,
            depProject,
            depProject.getBuild().getFinalName(),
            configSource);

    final String destName =
        AssemblyFormatUtils.evaluateFileNameMapping(
            dependencySet.getOutputFileNameMapping(),
            depArtifact,
            configSource.getProject(),
            moduleProject,
            moduleArtifact,
            depProject,
            configSource);

    String target;

    // omit the last char if ends with / or \\
    if (outputDirectory.endsWith("/") || outputDirectory.endsWith("\\")) {
      target = outputDirectory + destName;
    } else {
      target = outputDirectory + "/" + destName;
    }

    try {
      final int mode = TypeConversionUtils.modeToInt(dependencySet.getFileMode(), logger);
      if (mode > -1) {
        archiver.addFile(source, target, mode);
      } else {
        archiver.addFile(source, target);
      }
    } catch (final ArchiverException e) {
      throw new ArchiveCreationException("Error adding file to archive: " + e.getMessage(), e);
    }
  }
  private void checkMultiArtifactOutputConfig(final DependencySet dependencySet) {
    String dir = dependencySet.getOutputDirectory();
    if (dir == null) {
      dir = defaultOutputDirectory;
    }

    String mapping = dependencySet.getOutputFileNameMapping();
    if (mapping == null) {
      mapping = defaultOutputFileNameMapping;
    }

    if ((dir == null || dir.indexOf("${") < 0) && (mapping == null || mapping.indexOf("${") < 0)) {
      logger.warn(
          "NOTE: Your assembly specifies a dependencySet that matches multiple artifacts, but specifies a concrete output format. "
              + "THIS MAY RESULT IN ONE OR MORE ARTIFACTS BEING OBSCURED!\n\nOutput directory: '"
              + dir
              + "'\nOutput filename mapping: '"
              + mapping
              + "'");
    }
  }
  private void addNormalArtifact(
      final DependencySet dependencySet,
      final Artifact depArtifact,
      final MavenProject depProject,
      final Archiver archiver,
      final AssemblerConfigurationSource configSource)
      throws AssemblyFormattingException, ArchiveCreationException {
    logger.debug("Adding dependency artifact " + depArtifact.getId() + ".");

    final AddArtifactTask task = new AddArtifactTask(depArtifact, logger);

    task.setProject(depProject);
    task.setModuleProject(moduleProject);
    task.setModuleArtifact(moduleArtifact);
    task.setOutputDirectory(dependencySet.getOutputDirectory(), defaultOutputDirectory);
    task.setFileNameMapping(dependencySet.getOutputFileNameMapping(), defaultOutputFileNameMapping);

    final int dirMode = TypeConversionUtils.modeToInt(dependencySet.getDirectoryMode(), logger);
    if (dirMode != -1) {
      task.setDirectoryMode(dirMode);
    }

    final int fileMode = TypeConversionUtils.modeToInt(dependencySet.getFileMode(), logger);
    if (fileMode != -1) {
      task.setFileMode(fileMode);
    }

    task.setUnpack(dependencySet.isUnpack());

    final UnpackOptions opts = dependencySet.getUnpackOptions();
    if (dependencySet.isUnpack() && (opts != null)) {
      task.setIncludes(opts.getIncludes());
      task.setExcludes(opts.getExcludes());
    }

    task.execute(archiver, configSource);
  }
  protected Set<Artifact> resolveDependencyArtifacts(final DependencySet dependencySet)
      throws InvalidAssemblerConfigurationException {
    final Set<Artifact> dependencyArtifacts = new LinkedHashSet<Artifact>();
    if (resolvedArtifacts != null) {
      dependencyArtifacts.addAll(resolvedArtifacts);
    }

    if (dependencySet.isUseProjectArtifact()) {
      final Artifact projectArtifact = project.getArtifact();
      if ((projectArtifact != null) && (projectArtifact.getFile() != null)) {
        dependencyArtifacts.add(projectArtifact);
      } else {
        logger.warn(
            "Cannot include project artifact: "
                + projectArtifact
                + "; it doesn't have an associated file or directory.");
      }
    }

    if (dependencySet.isUseProjectAttachments()) {
      @SuppressWarnings("unchecked")
      final List<Artifact> attachments = project.getAttachedArtifacts();
      if (attachments != null) {
        for (final Iterator<Artifact> attachmentIt = attachments.iterator();
            attachmentIt.hasNext(); ) {
          final Artifact attachment = attachmentIt.next();

          if (attachment.getFile() != null) {
            dependencyArtifacts.add(attachment);
          } else {
            logger.warn(
                "Cannot include attached artifact: "
                    + project.getId()
                    + " for project: "
                    + project.getId()
                    + "; it doesn't have an associated file or directory.");
          }
        }
      }
    }

    if (dependencySet.isUseTransitiveFiltering()) {
      logger.debug("Filtering dependency artifacts USING transitive dependency path information.");
    } else {
      logger.debug(
          "Filtering dependency artifacts WITHOUT transitive dependency path information.");
    }

    final ScopeArtifactFilter filter = new ScopeArtifactFilter(dependencySet.getScope());

    FilterUtils.filterArtifacts(
        dependencyArtifacts,
        dependencySet.getIncludes(),
        dependencySet.getExcludes(),
        dependencySet.isUseStrictFiltering(),
        dependencySet.isUseTransitiveFiltering(),
        logger,
        filter);

    return dependencyArtifacts;
  }
  private void addFilteredUnpackedArtifact(
      final DependencySet dependencySet,
      final Artifact depArtifact,
      final MavenProject depProject,
      final Archiver archiver,
      final AssemblerConfigurationSource configSource)
      throws ArchiveCreationException, AssemblyFormattingException {
    logger.debug(
        "Adding dependency artifact "
            + depArtifact.getId()
            + " after filtering the unpacked contents.");

    final StringBuilder sb =
        new StringBuilder()
            .append(depArtifact.getGroupId())
            .append("_")
            .append(depArtifact.getArtifactId())
            .append("_")
            .append(depArtifact.getVersion());

    final String classifier = depArtifact.getClassifier();
    if (classifier != null) {
      sb.append("_").append(classifier);
    }

    sb.append(".").append(depArtifact.getType());

    final File dir = new File(configSource.getWorkingDirectory(), sb.toString());
    if (dir.exists()) {
      logger.debug(
          "NOT unpacking: "
              + depArtifact.getId()
              + ". Directory already exists in workdir:\n\t"
              + dir.getAbsolutePath());
    } else {
      dir.mkdirs();

      UnArchiver unarchiver;
      try {
        unarchiver = archiverManager.getUnArchiver(depArtifact.getFile());
      } catch (final NoSuchArchiverException e) {
        throw new ArchiveCreationException(
            "Failed to retrieve un-archiver for: "
                + depArtifact.getId()
                + ". Dependency filtering cannot proceed.",
            e);
      }

      unarchiver.setDestDirectory(dir);
      unarchiver.setOverwrite(true);
      unarchiver.setSourceFile(depArtifact.getFile());
      unarchiver.setIgnorePermissions(configSource.isIgnorePermissions());

      try {
        unarchiver.extract();
      } catch (final ArchiverException e) {
        throw new ArchiveCreationException(
            "Failed to unpack dependency archive: "
                + depArtifact.getId()
                + ". Dependency filtering cannot proceed.",
            e);
      }
    }

    final UnpackOptions opts = dependencySet.getUnpackOptions();

    final FileSet fs = new FileSet();
    fs.setDirectory(dir.getAbsolutePath());
    fs.setDirectoryMode(dependencySet.getDirectoryMode());
    fs.setExcludes(opts.getExcludes());
    fs.setFileMode(dependencySet.getFileMode());
    fs.setFiltered(opts.isFiltered());
    fs.setIncludes(opts.getIncludes());

    String outDir = dependencySet.getOutputDirectory();
    if (outDir == null) {
      outDir = defaultOutputDirectory;
    }

    String filenameMapping = dependencySet.getOutputFileNameMapping();
    if (filenameMapping == null) {
      filenameMapping = defaultOutputFileNameMapping;
    }

    filenameMapping =
        AssemblyFormatUtils.evaluateFileNameMapping(
            filenameMapping,
            depArtifact,
            configSource.getProject(),
            moduleProject,
            moduleArtifact,
            depProject,
            configSource);

    final String outputLocation = new File(outDir, filenameMapping).getPath();

    fs.setOutputDirectory(outputLocation);

    fs.setLineEnding(opts.getLineEnding());
    fs.setUseDefaultExcludes(opts.isUseDefaultExcludes());

    final AddFileSetsTask task = new AddFileSetsTask(fs);
    task.setProject(depProject);
    task.setModuleProject(moduleProject);
    task.setLogger(logger);

    task.execute(archiver, configSource);
  }
  protected void addDependencySet(
      final DependencySet dependencySet,
      final Archiver archiver,
      final AssemblerConfigurationSource configSource)
      throws AssemblyFormattingException, ArchiveCreationException,
          InvalidAssemblerConfigurationException {
    logger.debug("Processing DependencySet (output=" + dependencySet.getOutputDirectory() + ")");

    if (!dependencySet.isUseTransitiveDependencies() && dependencySet.isUseTransitiveFiltering()) {
      logger.warn(
          "DependencySet has nonsensical configuration: useTransitiveDependencies == false "
              + "AND useTransitiveFiltering == true. Transitive filtering flag will be ignored.");
    }

    final Set<Artifact> dependencyArtifacts = resolveDependencyArtifacts(dependencySet);

    boolean filterContents = false;
    final UnpackOptions opts = dependencySet.getUnpackOptions();
    if (dependencySet.isUnpack()
        && opts != null
        && (opts.isFiltered() || opts.getLineEnding() != null)) {
      filterContents = true;
    } else if (dependencyArtifacts.size() > 1) {
      checkMultiArtifactOutputConfig(dependencySet);
    }

    logger.debug("Adding " + dependencyArtifacts.size() + " dependency artifacts.");

    for (final Iterator<Artifact> j = dependencyArtifacts.iterator(); j.hasNext(); ) {
      final Artifact depArtifact = j.next();

      MavenProject depProject;
      try {
        depProject =
            projectBuilder.buildFromRepository(
                depArtifact,
                configSource.getRemoteRepositories(),
                configSource.getLocalRepository());
      } catch (final ProjectBuildingException e) {
        logger.debug(
            "Error retrieving POM of module-dependency: "
                + depArtifact.getId()
                + "; Reason: "
                + e.getMessage()
                + "\n\nBuilding stub project instance.");

        depProject = buildProjectStub(depArtifact);
      }

      if (NON_ARCHIVE_DEPENDENCY_TYPES.contains(depArtifact.getType())) {
        addNonArchiveDependency(depArtifact, depProject, dependencySet, archiver, configSource);
      } else {
        if (filterContents) {
          addFilteredUnpackedArtifact(
              dependencySet, depArtifact, depProject, archiver, configSource);
        } else {
          addNormalArtifact(dependencySet, depArtifact, depProject, archiver, configSource);
        }
      }
    }
  }