1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.incubator.jpackage.internal;
  27 
  28 import java.io.IOException;
  29 import java.nio.file.Files;
  30 import java.nio.file.Path;
  31 import java.util.Map;
  32 import java.util.Objects;
  33 import java.util.Optional;
  34 import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
  35 import static jdk.incubator.jpackage.internal.StandardBundlerParam.APP_NAME;
  36 import static jdk.incubator.jpackage.internal.StandardBundlerParam.CONFIG_ROOT;
  37 
  38 /**
  39  * Runs custom script from resource directory.
  40  */
  41 class ScriptRunner {
  42     ScriptRunner() {
  43         environment = new ProcessBuilder().environment();
  44     }
  45 
  46     ScriptRunner setResourceCategoryId(String v) {
  47         resourceCategoryId = v;
  48         return this;
  49     }
  50 
  51     ScriptRunner setDirectory(Path v) {
  52         directory = v;
  53         return this;
  54     }
  55 
  56     ScriptRunner setScriptNameSuffix(String v) {
  57         scriptNameSuffix = v;
  58         return this;
  59     }
  60 
  61     ScriptRunner addEnvironment(Map<String, String> v) {
  62         environment.putAll(v);
  63         return this;
  64     }
  65 
  66     ScriptRunner setEnvironmentVariable(String envVarName, String envVarValue) {
  67         Objects.requireNonNull(envVarName);
  68         if (envVarValue == null) {
  69             environment.remove(envVarName);
  70         } else {
  71             environment.put(envVarName, envVarValue);
  72         }
  73         return this;
  74     }
  75 
  76     public void run(Map<String, ? super Object> params) throws IOException {
  77         String scriptName = String.format("%s-%s%s", APP_NAME.fetchFrom(params),
  78                 scriptNameSuffix, scriptSuffix());
  79         Path scriptPath = CONFIG_ROOT.fetchFrom(params).toPath().resolve(
  80                 scriptName);
  81         createResource(null, params)
  82                 .setCategory(I18N.getString(resourceCategoryId))
  83                 .saveToFile(scriptPath);
  84         if (!Files.exists(scriptPath)) {
  85             return;
  86         }
  87 
  88         ProcessBuilder pb = new ProcessBuilder(shell(),
  89                 scriptPath.toAbsolutePath().toString());
  90         Map<String, String> workEnvironment = pb.environment();
  91         workEnvironment.clear();
  92         workEnvironment.putAll(environment);
  93 
  94         if (directory != null) {
  95             pb.directory(directory.toFile());
  96         }
  97 
  98         Executor.of(pb).executeExpectSuccess();
  99     }
 100 
 101     private static String shell() {
 102         if (Platform.isWindows()) {
 103             return "cscript";
 104         }
 105         return Optional.ofNullable(System.getenv("SHELL")).orElseGet(() -> "sh");
 106     }
 107 
 108     private static String scriptSuffix() {
 109         if (Platform.isWindows()) {
 110             return ".wsf";
 111         }
 112         return ".sh";
 113     }
 114 
 115     private String scriptNameSuffix;
 116     private String resourceCategoryId;
 117     private Path directory;
 118     private Map<String, String> environment;
 119 }