protected void releaseAfterClose(
     final Parameters parameters,
     final RemoteNexus remoteNexus,
     final List<StagingRepository> stagedRepositories)
     throws MojoExecutionException {
   getLogger().info("Remote staging repositories are being released...");
   final List<String> stagedRepositoryIds =
       Lists.newArrayList(
           Collections2.transform(
               stagedRepositories,
               new Function<StagingRepository, String>() {
                 @Override
                 public String apply(StagingRepository input) {
                   return input.getRepositoryId();
                 }
               }));
   final StagingWorkflowV2Service stagingWorkflow = remoteNexus.getStagingWorkflowV2Service();
   try {
     if (stagingWorkflow instanceof StagingWorkflowV3Service) {
       final StagingWorkflowV3Service v3 = (StagingWorkflowV3Service) stagingWorkflow;
       StagingActionDTO action = new StagingActionDTO();
       action.setDescription(parameters.getActionDescription(StagingAction.RELEASE));
       action.setStagedRepositoryIds(stagedRepositoryIds);
       action.setAutoDropAfterRelease(parameters.isAutoDropAfterRelease());
       v3.releaseStagingRepositories(action);
     } else {
       stagingWorkflow.releaseStagingRepositories(
           parameters.getActionDescription(StagingAction.RELEASE),
           stagedRepositoryIds.toArray(new String[stagedRepositoryIds.size()]));
     }
   } catch (NexusClientErrorResponseException e) {
     ErrorDumper.dumpErrors(getLogger(), e);
     // fail the build
     throw new MojoExecutionException(
         "Could not perform action: Nexus ErrorResponse received!", e);
   } catch (StagingRuleFailuresException e) {
     ErrorDumper.dumpErrors(getLogger(), e);
     // fail the build
     throw new MojoExecutionException(
         "Could not perform action: there are failing staging rules!", e);
   }
   getLogger().info("Remote staging repositories released.");
 }
  /** Performs Nexus staging of locally staged artifacts. */
  @Override
  public void finalizeDeploy(final FinalizeDeployRequest request)
      throws ArtifactDeploymentException, MojoExecutionException {
    getLogger().info("Performing remote staging...");
    final File stageRoot = request.getParameters().getStagingDirectoryRoot();
    final File[] localStageRepositories = stageRoot.listFiles();
    if (localStageRepositories == null) {
      getLogger().info("We have nothing locally staged, bailing out.");
      return;
    }
    final RemoteNexus remoteNexus =
        checkNotNull(
            request.getRemoteNexus(), "BUG: finalizeDeploy invoked before deployPerModule?");
    final List<StagingRepository> zappedStagingRepositories = new ArrayList<StagingRepository>();
    for (File profileDirectory : localStageRepositories) {
      if (!profileDirectory.isDirectory()) {
        continue;
      }

      // we do remote staging
      final String profileId = profileDirectory.getName();
      getLogger().info("");
      getLogger().info(" * Remote staging into staging profile ID \"" + profileId + "\"");

      try {
        final Profile stagingProfile =
            remoteNexus.getStagingWorkflowV2Service().selectProfile(profileId);
        final StagingRepository stagingRepository =
            beforeUpload(request.getParameters(), remoteNexus, stagingProfile);
        zappedStagingRepositories.add(stagingRepository);
        getLogger()
            .info(" * Uploading locally staged artifacts to profile " + stagingProfile.name());
        deployUp(
            request.getMavenSession(),
            getStagingDirectory(request.getParameters().getStagingDirectoryRoot(), profileId),
            createDeploymentArtifactRepository(
                remoteNexus.getServer().getId(), stagingRepository.getUrl()));
        getLogger().info(" * Upload of locally staged artifacts finished.");
        afterUpload(request.getParameters(), remoteNexus, stagingRepository);
      } catch (NexusClientNotFoundException e) {
        afterUploadFailure(request.getParameters(), remoteNexus, zappedStagingRepositories, e);
        getLogger().error("Remote staging finished with a failure: " + e.getMessage());
        getLogger().error("");
        getLogger().error("Possible causes of 404 Not Found error:");
        getLogger()
            .error(
                " * your local workspace is \"dirty\" with previous runs, that locally staged artifacts? Run \"mvn clean\"...");
        getLogger()
            .error(
                " * remote Nexus got the profile with ID \""
                    + profileId
                    + "\" removed during this build? Get to Nexus admin...");
        throw new ArtifactDeploymentException("Remote staging failed: " + e.getMessage(), e);
      } catch (NexusClientAccessForbiddenException e) {
        afterUploadFailure(request.getParameters(), remoteNexus, zappedStagingRepositories, e);
        getLogger().error("Remote staging finished with a failure: " + e.getMessage());
        getLogger().error("");
        getLogger().error("Possible causes of 403 Forbidden:");
        getLogger()
            .error(
                " * you have no permissions to stage against profile with ID \""
                    + profileId
                    + "\"? Get to Nexus admin...");
        throw new ArtifactDeploymentException("Remote staging failed: " + e.getMessage(), e);
      } catch (Exception e) {
        afterUploadFailure(request.getParameters(), remoteNexus, zappedStagingRepositories, e);
        getLogger().error("Remote staging finished with a failure: " + e.getMessage());
        throw new ArtifactDeploymentException("Remote staging failed: " + e.getMessage(), e);
      }
    }
    getLogger()
        .info(
            "Remote staged "
                + zappedStagingRepositories.size()
                + " repositories, finished with success.");

    if (!request.getParameters().isSkipStagingRepositoryClose()
        && request.getParameters().isAutoReleaseAfterClose()) {
      releaseAfterClose(request.getParameters(), remoteNexus, zappedStagingRepositories);
    }
  }