// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/lib/OutputAdapter.java
// public interface OutputAdapter {
//     void logInfo(String message);
//     void logDebug(String message);
//     void logWarn(String message);
//     void logError(String message);
//     void logUploadProgress(long uploaded, long contentLength);
// 
//     default void logError(String message, Throwable t) {
//         logError(message);
//         logDebug(Arrays.stream(t.getStackTrace()).map(StackTraceElement::toString).collect(Collectors.joining("\n")));
//     }
// }
// 
// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/lib/running/RunWebApp.java
// public class RunWebApp {
// 
//     public static void run(Path warFile, List<String> javaOptions, List<String> webappRunnerOptions, String webappRunnerVersion, OutputAdapter outputAdapter) throws IOException, InterruptedException {
//         outputAdapter.logInfo("Downloading webapp-runner...");
//         Path webappRunnerJarPath = null;
//         try {
//              webappRunnerJarPath = FileDownloader.download(WebappRunnerResolver.getUrlForVersion(webappRunnerVersion));
//         } catch (FileNotFoundException e) {
//             outputAdapter.logDebug(String.format("Could not download webapp-runner %s. Please check if this is a valid version.", webappRunnerVersion));
//             System.exit(-1);
//         }
// 
//         ArrayList<String> command = new ArrayList<>();
//         command.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
//         command.addAll(javaOptions);
//         command.add("-jar");
//         command.add(webappRunnerJarPath.toString());
//         command.addAll(webappRunnerOptions);
//         command.add(warFile.toString());
// 
//         ProcessBuilder processBuilder = new ProcessBuilder(command.toArray(new String[0]));
//         Process process = processBuilder.start();
// 
//         StreamGobbler stdOutStreamGobbler = new StreamGobbler(process.getInputStream(), outputAdapter);
//         StreamGobbler stdErrStreamGobbler = new StreamGobbler(process.getErrorStream(), outputAdapter);
// 
//         stdOutStreamGobbler.start();
//         stdErrStreamGobbler.start();
// 
//         process.waitFor();
//     }
// 
//     private static class StreamGobbler extends Thread {
//         private InputStream inputStream;
//         private OutputAdapter outputAdapter;
// 
//         public StreamGobbler(InputStream inputStream, OutputAdapter outputAdapter) {
//             super("StreamGobbler");
//             this.inputStream = inputStream;
//             this.outputAdapter = outputAdapter;
//         }
// 
//         public void run() {
//             try {
//                 BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
//                 String line;
// 
//                 while ((line = br.readLine()) != null) {
//                     outputAdapter.logInfo(line);
//                 }
//             } catch (IOException e) {
//                 outputAdapter.logError(e.getMessage(), e);
//                 throw new RuntimeException(e);
//             }
//         }
//     }
// }
// 
// Path: heroku-maven-plugin/src/main/java/com/heroku/sdk/maven/MavenLogOutputAdapter.java
// public class MavenLogOutputAdapter implements OutputAdapter {
//     private final Log log;
//     private boolean logUploadProgress;
// 
//     public MavenLogOutputAdapter(Log log, boolean logUploadProgress) {
//         this.log = log;
//         this.logUploadProgress = logUploadProgress;
//     }
// 
//     @Override
//     public void logInfo(String message) {
//         log.info(message);
//     }
// 
//     @Override
//     public void logDebug(String message) {
//         log.debug(message);
//     }
// 
//     @Override
//     public void logWarn(String message) {
//         log.warn(message);
//     }
// 
//     @Override
//     public void logError(String message) {
//         log.error(message);
//     }
// 
//     @Override
//     public void logUploadProgress(long uploaded, long contentLength) {
//         if (logUploadProgress) {
//             log.debug("[" + uploaded + "/" + contentLength + "]");
//         }
//     }
// }


import com.heroku.sdk.deploy.lib.OutputAdapter;
import com.heroku.sdk.deploy.lib.running.RunWebApp;
import com.heroku.sdk.maven.MavenLogOutputAdapter;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import java.io.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
package com.heroku.sdk.maven.mojo;



/**
 * Starts the web application in a way that is very similar to how it is run on Heroku. JAVA_OPTS and WEBAPP_RUNNER_OPTS
 * specified in configVars will also be picked up by this goal and used to run your application.
 */
@Mojo(name = "run-war", requiresDependencyResolution = ResolutionScope.RUNTIME)
@Execute(phase = LifecyclePhase.PACKAGE)
public class RunWarMojo extends AbstractHerokuMojo {

  @Override
  public void execute() throws MojoExecutionException {
    OutputAdapter outputAdapter = new MavenLogOutputAdapter(getLog(), logProgress);

    Path projectDirectory = super.mavenProject.getBasedir().toPath();

    List<String> javaOptions = splitOptions(configVars.getOrDefault("JAVA_OPTS", ""));
    List<String> webappRunnerOptions = splitOptions(configVars.getOrDefault("WEBAPP_RUNNER_OPTS", ""));

    Path warFilePath = null;
    try {
      warFilePath = findWarFilePath(projectDirectory).orElseThrow(() -> new MojoExecutionException("Could not find WAR file to run!"));
    } catch (IOException e) {
      throw new MojoExecutionException("Could not find WAR file to run!", e);
    }

    try {
// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/lib/OutputAdapter.java
// public interface OutputAdapter {
//     void logInfo(String message);
//     void logDebug(String message);
//     void logWarn(String message);
//     void logError(String message);
//     void logUploadProgress(long uploaded, long contentLength);
// 
//     default void logError(String message, Throwable t) {
//         logError(message);
//         logDebug(Arrays.stream(t.getStackTrace()).map(StackTraceElement::toString).collect(Collectors.joining("\n")));
//     }
// }
// 
// Path: heroku-deploy/src/main/java/com/heroku/sdk/deploy/lib/running/RunWebApp.java
// public class RunWebApp {
// 
//     public static void run(Path warFile, List<String> javaOptions, List<String> webappRunnerOptions, String webappRunnerVersion, OutputAdapter outputAdapter) throws IOException, InterruptedException {
//         outputAdapter.logInfo("Downloading webapp-runner...");
//         Path webappRunnerJarPath = null;
//         try {
//              webappRunnerJarPath = FileDownloader.download(WebappRunnerResolver.getUrlForVersion(webappRunnerVersion));
//         } catch (FileNotFoundException e) {
//             outputAdapter.logDebug(String.format("Could not download webapp-runner %s. Please check if this is a valid version.", webappRunnerVersion));
//             System.exit(-1);
//         }
// 
//         ArrayList<String> command = new ArrayList<>();
//         command.add(System.getProperty("java.home") + File.separator + "bin" + File.separator + "java");
//         command.addAll(javaOptions);
//         command.add("-jar");
//         command.add(webappRunnerJarPath.toString());
//         command.addAll(webappRunnerOptions);
//         command.add(warFile.toString());
// 
//         ProcessBuilder processBuilder = new ProcessBuilder(command.toArray(new String[0]));
//         Process process = processBuilder.start();
// 
//         StreamGobbler stdOutStreamGobbler = new StreamGobbler(process.getInputStream(), outputAdapter);
//         StreamGobbler stdErrStreamGobbler = new StreamGobbler(process.getErrorStream(), outputAdapter);
// 
//         stdOutStreamGobbler.start();
//         stdErrStreamGobbler.start();
// 
//         process.waitFor();
//     }
// 
//     private static class StreamGobbler extends Thread {
//         private InputStream inputStream;
//         private OutputAdapter outputAdapter;
// 
//         public StreamGobbler(InputStream inputStream, OutputAdapter outputAdapter) {
//             super("StreamGobbler");
//             this.inputStream = inputStream;
//             this.outputAdapter = outputAdapter;
//         }
// 
//         public void run() {
//             try {
//                 BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
//                 String line;
// 
//                 while ((line = br.readLine()) != null) {
//                     outputAdapter.logInfo(line);
//                 }
//             } catch (IOException e) {
//                 outputAdapter.logError(e.getMessage(), e);
//                 throw new RuntimeException(e);
//             }
//         }
//     }
// }
// 
// Path: heroku-maven-plugin/src/main/java/com/heroku/sdk/maven/MavenLogOutputAdapter.java
// public class MavenLogOutputAdapter implements OutputAdapter {
//     private final Log log;
//     private boolean logUploadProgress;
// 
//     public MavenLogOutputAdapter(Log log, boolean logUploadProgress) {
//         this.log = log;
//         this.logUploadProgress = logUploadProgress;
//     }
// 
//     @Override
//     public void logInfo(String message) {
//         log.info(message);
//     }
// 
//     @Override
//     public void logDebug(String message) {
//         log.debug(message);
//     }
// 
//     @Override
//     public void logWarn(String message) {
//         log.warn(message);
//     }
// 
//     @Override
//     public void logError(String message) {
//         log.error(message);
//     }
// 
//     @Override
//     public void logUploadProgress(long uploaded, long contentLength) {
//         if (logUploadProgress) {
//             log.debug("[" + uploaded + "/" + contentLength + "]");
//         }
//     }
// }


// Path: heroku-maven-plugin/src/main/java/com/heroku/sdk/maven/mojo/RunWarMojo.java
import com.heroku.sdk.deploy.lib.OutputAdapter;
import com.heroku.sdk.deploy.lib.running.RunWebApp;
import com.heroku.sdk.maven.MavenLogOutputAdapter;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Execute;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import java.io.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

package com.heroku.sdk.maven.mojo;



/**
 * Starts the web application in a way that is very similar to how it is run on Heroku. JAVA_OPTS and WEBAPP_RUNNER_OPTS
 * specified in configVars will also be picked up by this goal and used to run your application.
 */
@Mojo(name = "run-war", requiresDependencyResolution = ResolutionScope.RUNTIME)
@Execute(phase = LifecyclePhase.PACKAGE)
public class RunWarMojo extends AbstractHerokuMojo {

  @Override
  public void execute() throws MojoExecutionException {
    OutputAdapter outputAdapter = new MavenLogOutputAdapter(getLog(), logProgress);

    Path projectDirectory = super.mavenProject.getBasedir().toPath();

    List<String> javaOptions = splitOptions(configVars.getOrDefault("JAVA_OPTS", ""));
    List<String> webappRunnerOptions = splitOptions(configVars.getOrDefault("WEBAPP_RUNNER_OPTS", ""));

    Path warFilePath = null;
    try {
      warFilePath = findWarFilePath(projectDirectory).orElseThrow(() -> new MojoExecutionException("Could not find WAR file to run!"));
    } catch (IOException e) {
      throw new MojoExecutionException("Could not find WAR file to run!", e);
    }

    try {
      RunWebApp.run(warFilePath, javaOptions, webappRunnerOptions, webappRunnerVersion, outputAdapter);