Servant.java

  1. package Hoot.Compiler.Mojo;

  2. import java.io.*;
  3. import java.util.Properties;
  4. import org.apache.commons.lang3.SystemUtils;
  5. import org.eclipse.aether.artifact.Artifact;
  6. import static Hoot.Runtime.Functions.Exceptional.*;
  7. import Hoot.Runtime.Faces.Logging;

  8. /**
  9.  * Compiles Hoot code in a separate process.
  10.  *
  11.  * @author nik <nikboyd@sonic.net>
  12.  * @see "Copyright 2010,2021 Nikolas S Boyd."
  13.  * @see "Permission is granted to copy this work provided this copyright statement is retained in all copies."
  14.  */
  15. public class Servant implements Logging {

  16.     private Process remoteProcess = null;
  17.     public void runCompiler(String... args) {
  18.         runLoudly(() -> {
  19.             remoteProcess = buildProcess(args).start();
  20.             new Thread(() -> pipeShellOutput()).start();
  21.             remoteProcess.waitFor();
  22.         });
  23.     }

  24.     InputStream processStream() { return remoteProcess.getInputStream(); }
  25.     BufferedReader processReader() { return new BufferedReader(new InputStreamReader(processStream())); }
  26.     void pipeShellOutput() {
  27.         String line; BufferedReader reader = processReader();
  28.         try { while((line = reader.readLine()) != null) report(line); }
  29.         catch (IOException x) { error(x); }
  30.     }

  31.     Properties p = new Properties();
  32.     static final String Version = "version"; // loaded value name
  33.     static final String MojoVersion = "/version.properties";
  34.     String version() { runLoudly(() -> loadVersion(p)); return p.getProperty(Version); }
  35.     void loadVersion(Properties p) throws IOException { try (InputStream in = versionStream()) { p.load(in); } }
  36.     InputStream versionStream() throws IOException { return getClass().getResourceAsStream(MojoVersion); }

  37.     static final String CompilerSpec = "hoot-smalltalk:hoot-compiler-boot:";
  38.     Artifact locateArtifact() { return Discovery.lookup(CompilerSpec + version()).getArtifact(); }
  39.     String locateCompiler() { return locateArtifact().getFile().getAbsolutePath(); }

  40.     static final String Quote = "\"";
  41.     static final String WinShell = "cmd.exe";
  42.     static final String WinCommand = "'%%JAVA_HOME%%\\bin\\java' -jar %s";
  43.     String buildWinCommand(String... args) {
  44.         String result = format(WinCommand, locateCompiler()).replace("'", Quote);
  45.         for (String s : args) { result += " " + s; }
  46.         report("running "+result);
  47.         return result; }

  48.     static final String Shell = "/bin/sh";
  49.     static final String JavaCommand = "$JAVA_HOME/bin/java -jar %s";
  50.     String buildJavaCommand(String... args) {
  51.         String result = format(JavaCommand, locateCompiler());
  52.         for (String s : args) { result += " " + s; }
  53.         report("running "+result);
  54.         return result; }

  55.     ProcessBuilder buildProcess(String... args) {
  56.         return SystemUtils.IS_OS_WINDOWS ?
  57.             new ProcessBuilder(WinShell, "/c", buildWinCommand(args)) :
  58.             new ProcessBuilder(Shell, "-c", buildJavaCommand(args)); }

  59. } // Servant