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 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);
  }
  /**
   * Create the binary distribution.
   *
   * @throws org.apache.maven.plugin.MojoExecutionException
   */
  public void execute() throws MojoExecutionException, MojoFailureException {
    if (skipAssembly) {
      getLog()
          .info("Assemblies have been skipped per configuration of the skipAssembly parameter.");
      return;
    }

    // run only at the execution root.
    if (runOnlyAtExecutionRoot && !isThisTheExecutionRoot()) {
      getLog().info("Skipping the assembly in this project because it's not the Execution Root");
      return;
    }

    List<Assembly> assemblies;
    try {
      assemblies = assemblyReader.readAssemblies(this);
    } catch (final AssemblyReadException e) {
      throw new MojoExecutionException("Error reading assemblies: " + e.getMessage(), e);
    } catch (final InvalidAssemblerConfigurationException e) {
      throw new MojoFailureException(
          assemblyReader, e.getMessage(), "Mojo configuration is invalid: " + e.getMessage());
    }

    // TODO: include dependencies marked for distribution under certain formats
    // TODO: how, might we plug this into an installer, such as NSIS?

    boolean warnedAboutMainProjectArtifact = false;
    for (final Assembly assembly : assemblies) {
      try {
        final String fullName = AssemblyFormatUtils.getDistributionName(assembly, this);

        List<String> effectiveFormats = formats;
        if (effectiveFormats == null || effectiveFormats.size() == 0) {
          effectiveFormats = assembly.getFormats();
        }
        if (effectiveFormats == null || effectiveFormats.size() == 0) {
          throw new MojoFailureException(
              "No formats specified in the execution parameters or the assembly descriptor.");
        }

        for (final String format : effectiveFormats) {
          final File destFile =
              assemblyArchiver.createArchive(
                  assembly, fullName, format, this, isRecompressZippedFiles());

          final MavenProject project = getProject();
          final String classifier = getClassifier();
          final String type = project.getArtifact().getType();

          if (attach && destFile.isFile()) {
            if (isAssemblyIdAppended()) {
              projectHelper.attachArtifact(project, format, assembly.getId(), destFile);
            } else if (classifier != null) {
              projectHelper.attachArtifact(project, format, classifier, destFile);
            } else if (!"pom".equals(type) && format.equals(type)) {
              if (!warnedAboutMainProjectArtifact) {
                final StringBuilder message = new StringBuilder();

                message.append(
                    "Configuration options: 'appendAssemblyId' is set to false, and 'classifier' is missing.");
                message
                    .append("\nInstead of attaching the assembly file: ")
                    .append(destFile)
                    .append(", it will become the file for main project artifact.");
                message.append(
                    "\nNOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!");

                getLog().warn(message);
                warnedAboutMainProjectArtifact = true;
              }

              final File existingFile = project.getArtifact().getFile();
              if ((existingFile != null) && existingFile.exists()) {
                getLog()
                    .warn(
                        "Replacing pre-existing project main-artifact file: "
                            + existingFile
                            + "\nwith assembly file: "
                            + destFile);
              }

              project.getArtifact().setFile(destFile);
            } else {
              projectHelper.attachArtifact(project, format, null, destFile);
            }
          } else if (attach) {
            getLog()
                .warn(
                    "Assembly file: "
                        + destFile
                        + " is not a regular file (it may be a directory). It cannot be attached to the project build for installation or deployment.");
          }
        }
      } catch (final ArchiveCreationException e) {
        throw new MojoExecutionException("Failed to create assembly: " + e.getMessage(), e);
      } catch (final AssemblyFormattingException e) {
        throw new MojoExecutionException("Failed to create assembly: " + e.getMessage(), e);
      } catch (final InvalidAssemblerConfigurationException e) {
        throw new MojoFailureException(
            assembly,
            "Assembly is incorrectly configured: " + assembly.getId(),
            "Assembly: " + assembly.getId() + " is not configured correctly: " + e.getMessage());
      }
    }
  }