// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/Constants.java
// public class Constants {
//     public static final String DEFAULT_WEBAPP_RUNNER_VERSION = "9.0.30.0";
// }
// 
// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/util/PathUtils.java
// public class PathUtils {
// 
//     public static List<Path> normalizeAll(Path basePath, List<Path> paths) {
//         List<Path> normalizedPaths = new ArrayList<>();
//         for (Path path : paths) {
//             normalize(basePath, path).ifPresent(normalizedPaths::add);
//         }
// 
//         return normalizedPaths;
//     }
// 
//     public static Optional<Path> normalize(Path basePath, Path path) {
//         Path absoluteBasePath = basePath.toAbsolutePath();
//         Path normalizedAbsolutePath = absoluteBasePath.resolve(path).normalize();
// 
//         if (normalizedAbsolutePath.startsWith(absoluteBasePath)) {
//             return Optional.of(absoluteBasePath.relativize(normalizedAbsolutePath));
//         }
// 
//         return Optional.empty();
//     }
// 
//     public static boolean isValidPath(Path basePath, Path path) {
//         return normalize(basePath, path).isPresent();
//     }
// 
//     public static List<Path> expandDirectories(Path basePath, List<Path> paths) throws IOException {
//         ArrayList<Path> result = new ArrayList<>();
//         for (Path path : paths) {
//             result.addAll(expandDirectory(basePath, path));
//         }
// 
//         return result;
//     }
// 
//     public static List<Path> expandDirectory(Path basePath, Path path) throws IOException {
//         return Files
//                 .walk(basePath.resolve(path).normalize())
//                 .filter(subPath -> !Files.isDirectory(subPath))
//                 .map(subPath -> normalize(basePath, subPath))
//                 .filter(Optional::isPresent)
//                 .map(Optional::get)
//                 .collect(Collectors.toList());
//     }
// 
//     public static String separatorsToUnix(Path path) {
//         // Path will normalize separators back to Windows when run on Windows. We have to fall back to a String here.
//         return path.toString().replace('\\', '/');
//     }
// }


import com.heroku.sdk.deploy.Constants;
import com.heroku.sdk.deploy.util.PathUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
   * The path to the war file that will be deployed with the `deploy-war` target.
   */
  @Parameter(name="warFile")
  protected String warFile = null;

  /**
   * The version of webapp-runner to use.
   */
  @Parameter(name="webappRunnerVersion")
  protected String webappRunnerVersion = Constants.DEFAULT_WEBAPP_RUNNER_VERSION;

  /**
   * Common helper to find the projects WAR file either by referencing the explicitly configured WAR file or searching
   * the build directory for a WAR file. This implementation assumes it is run as part of a goal and will throw
   * MojoExecutionExceptions with user-facing error messages.
   *
   * @param projectDirectory The root directory of the project
   * @return An optional Path to the WAR file if one could be found
   * @throws MojoExecutionException If there is no explicitly configured WAR file path or the projects packaged as a WAR
   * @throws IOException If an IO error occurred during WAR file search
   */
  protected Optional<Path> findWarFilePath(Path projectDirectory) throws MojoExecutionException, IOException {
    if (warFile == null) {
      if (!mavenProject.getPackaging().equals("war")) {
        throw new MojoExecutionException("Your packaging must be set to 'war' or you must define the '<warFile>' config to use this goal!");
      }

      return Files
              .find(Paths.get(mavenProject.getBuild().getDirectory()), Integer.MAX_VALUE, (path, attributes) -> path.toString().endsWith(".war"))
              .findFirst()
// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/Constants.java
// public class Constants {
//     public static final String DEFAULT_WEBAPP_RUNNER_VERSION = "9.0.30.0";
// }
// 
// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/util/PathUtils.java
// public class PathUtils {
// 
//     public static List<Path> normalizeAll(Path basePath, List<Path> paths) {
//         List<Path> normalizedPaths = new ArrayList<>();
//         for (Path path : paths) {
//             normalize(basePath, path).ifPresent(normalizedPaths::add);
//         }
// 
//         return normalizedPaths;
//     }
// 
//     public static Optional<Path> normalize(Path basePath, Path path) {
//         Path absoluteBasePath = basePath.toAbsolutePath();
//         Path normalizedAbsolutePath = absoluteBasePath.resolve(path).normalize();
// 
//         if (normalizedAbsolutePath.startsWith(absoluteBasePath)) {
//             return Optional.of(absoluteBasePath.relativize(normalizedAbsolutePath));
//         }
// 
//         return Optional.empty();
//     }
// 
//     public static boolean isValidPath(Path basePath, Path path) {
//         return normalize(basePath, path).isPresent();
//     }
// 
//     public static List<Path> expandDirectories(Path basePath, List<Path> paths) throws IOException {
//         ArrayList<Path> result = new ArrayList<>();
//         for (Path path : paths) {
//             result.addAll(expandDirectory(basePath, path));
//         }
// 
//         return result;
//     }
// 
//     public static List<Path> expandDirectory(Path basePath, Path path) throws IOException {
//         return Files
//                 .walk(basePath.resolve(path).normalize())
//                 .filter(subPath -> !Files.isDirectory(subPath))
//                 .map(subPath -> normalize(basePath, subPath))
//                 .filter(Optional::isPresent)
//                 .map(Optional::get)
//                 .collect(Collectors.toList());
//     }
// 
//     public static String separatorsToUnix(Path path) {
//         // Path will normalize separators back to Windows when run on Windows. We have to fall back to a String here.
//         return path.toString().replace('\\', '/');
//     }
// }


// Path: heroku-maven-plugin/src/main/java/com/heroku/sdk/maven/mojo/AbstractHerokuMojo.java
import com.heroku.sdk.deploy.Constants;
import com.heroku.sdk.deploy.util.PathUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.BuildPluginManager;
import org.apache.maven.plugin.Mojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

   * The path to the war file that will be deployed with the `deploy-war` target.
   */
  @Parameter(name="warFile")
  protected String warFile = null;

  /**
   * The version of webapp-runner to use.
   */
  @Parameter(name="webappRunnerVersion")
  protected String webappRunnerVersion = Constants.DEFAULT_WEBAPP_RUNNER_VERSION;

  /**
   * Common helper to find the projects WAR file either by referencing the explicitly configured WAR file or searching
   * the build directory for a WAR file. This implementation assumes it is run as part of a goal and will throw
   * MojoExecutionExceptions with user-facing error messages.
   *
   * @param projectDirectory The root directory of the project
   * @return An optional Path to the WAR file if one could be found
   * @throws MojoExecutionException If there is no explicitly configured WAR file path or the projects packaged as a WAR
   * @throws IOException If an IO error occurred during WAR file search
   */
  protected Optional<Path> findWarFilePath(Path projectDirectory) throws MojoExecutionException, IOException {
    if (warFile == null) {
      if (!mavenProject.getPackaging().equals("war")) {
        throw new MojoExecutionException("Your packaging must be set to 'war' or you must define the '<warFile>' config to use this goal!");
      }

      return Files
              .find(Paths.get(mavenProject.getBuild().getDirectory()), Integer.MAX_VALUE, (path, attributes) -> path.toString().endsWith(".war"))
              .findFirst()
              .flatMap(path -> PathUtils.normalize(projectDirectory, path));