< prev index next >

src/jdk.incubator.jpackage/windows/classes/jdk/incubator/jpackage/internal/WindowsAppImageBuilder.java

Print this page

        

@@ -21,11 +21,11 @@
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
-package jdk.jpackage.internal;
+package jdk.incubator.jpackage.internal;
 
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;

@@ -48,38 +48,38 @@
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
+import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
 
-import static jdk.jpackage.internal.StandardBundlerParam.*;
+import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
 
 public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
 
     static {
         System.loadLibrary("jpackage");
     }
 
     private static final ResourceBundle I18N = ResourceBundle.getBundle(
-            "jdk.jpackage.internal.resources.WinResources");
+            "jdk.incubator.jpackage.internal.resources.WinResources");
 
     private final static String LIBRARY_NAME = "applauncher.dll";
     private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll";
     private final static String REDIST_MSVCP = "msvcpVS_VER.dll";
 
-    private final static String TEMPLATE_APP_ICON ="javalogo_white_48.ico";
+    private final static String TEMPLATE_APP_ICON ="java48.ico";
 
     private static final String EXECUTABLE_PROPERTIES_TEMPLATE =
             "WinLauncher.template";
 
     private final Path root;
     private final Path appDir;
     private final Path appModsDir;
     private final Path runtimeDir;
     private final Path mdir;
-
-    private final Map<String, ? super Object> params;
+    private final Path binDir;
 
     public static final BundlerParamInfo<Boolean> REBRAND_EXECUTABLE =
             new WindowsBundlerParam<>(
             "win.launcher.rebrand",
             Boolean.class,

@@ -109,97 +109,49 @@
             // valueOf(null) is false,
             // and we actually do want null in some cases
             (s, p) -> (s == null
             || "null".equalsIgnoreCase(s)) ? true : Boolean.valueOf(s));
 
-    public WindowsAppImageBuilder(Map<String, Object> config, Path imageOutDir)
+    public WindowsAppImageBuilder(Map<String, Object> params, Path imageOutDir)
             throws IOException {
-        super(config,
-                imageOutDir.resolve(APP_NAME.fetchFrom(config) + "/runtime"));
+        super(params,
+                imageOutDir.resolve(APP_NAME.fetchFrom(params) + "/runtime"));
 
         Objects.requireNonNull(imageOutDir);
 
-        this.params = config;
-
         this.root = imageOutDir.resolve(APP_NAME.fetchFrom(params));
         this.appDir = root.resolve("app");
         this.appModsDir = appDir.resolve("mods");
         this.runtimeDir = root.resolve("runtime");
         this.mdir = runtimeDir.resolve("lib");
+        this.binDir = root;
         Files.createDirectories(appDir);
         Files.createDirectories(runtimeDir);
     }
 
-    public WindowsAppImageBuilder(String jreName, Path imageOutDir)
-            throws IOException {
-        super(null, imageOutDir.resolve(jreName));
-
-        Objects.requireNonNull(imageOutDir);
-
-        this.params = null;
-        this.root = imageOutDir.resolve(jreName);
-        this.appDir = null;
-        this.appModsDir = null;
-        this.runtimeDir = root;
-        this.mdir = runtimeDir.resolve("lib");
-        Files.createDirectories(runtimeDir);
-    }
-
-    private Path destFile(String dir, String filename) {
-        return runtimeDir.resolve(dir).resolve(filename);
-    }
-
     private void writeEntry(InputStream in, Path dstFile) throws IOException {
         Files.createDirectories(dstFile.getParent());
         Files.copy(in, dstFile);
     }
 
-    private void writeSymEntry(Path dstFile, Path target) throws IOException {
-        Files.createDirectories(dstFile.getParent());
-        Files.createLink(dstFile, target);
-    }
-
-    /**
-     * chmod ugo+x file
-     */
-    private void setExecutable(Path file) {
-        try {
-            Set<PosixFilePermission> perms =
-                Files.getPosixFilePermissions(file);
-            perms.add(PosixFilePermission.OWNER_EXECUTE);
-            perms.add(PosixFilePermission.GROUP_EXECUTE);
-            perms.add(PosixFilePermission.OTHERS_EXECUTE);
-            Files.setPosixFilePermissions(file, perms);
-        } catch (IOException ioe) {
-            throw new UncheckedIOException(ioe);
-        }
-    }
-
-    private static void createUtf8File(File file, String content)
-            throws IOException {
-        try (OutputStream fout = new FileOutputStream(file);
-             Writer output = new OutputStreamWriter(fout, "UTF-8")) {
-            output.write(content);
-        }
-    }
-
-    public static String getLauncherName(Map<String, ? super Object> p) {
-        return APP_NAME.fetchFrom(p) + ".exe";
+    private static String getLauncherName(Map<String, ? super Object> params) {
+        return APP_NAME.fetchFrom(params) + ".exe";
     }
 
     // Returns launcher resource name for launcher we need to use.
     public static String getLauncherResourceName(
-            Map<String, ? super Object> p) {
-        if (CONSOLE_HINT.fetchFrom(p)) {
+            Map<String, ? super Object> params) {
+        if (CONSOLE_HINT.fetchFrom(params)) {
             return "jpackageapplauncher.exe";
         } else {
             return "jpackageapplauncherw.exe";
         }
     }
 
-    public static String getLauncherCfgName(Map<String, ? super Object> p) {
-        return "app/" + APP_NAME.fetchFrom(p) +".cfg";
+    public static String getLauncherCfgName(
+            Map<String, ? super Object> params) {
+        return "app/" + APP_NAME.fetchFrom(params) +".cfg";
     }
 
     private File getConfig_AppIcon(Map<String, ? super Object> params) {
         return new File(getConfigRoot(params),
                 APP_NAME.fetchFrom(params) + ".ico");

@@ -224,31 +176,31 @@
     public Path getAppModsDir() {
         return appModsDir;
     }
 
     @Override
-    public void prepareApplicationFiles() throws IOException {
+    public void prepareApplicationFiles(Map<String, ? super Object> params)
+            throws IOException {
         Map<String, ? super Object> originalParams = new HashMap<>(params);
-        File rootFile = root.toFile();
-        if (!rootFile.isDirectory() && !rootFile.mkdirs()) {
-            throw new RuntimeException(MessageFormat.format(I18N.getString(
-                "error.cannot-create-output-dir"), rootFile.getAbsolutePath()));
-        }
-        if (!rootFile.canWrite()) {
-            throw new RuntimeException(MessageFormat.format(
-                    I18N.getString("error.cannot-write-to-output-dir"),
-                    rootFile.getAbsolutePath()));
+
+        try {
+            IOUtils.writableOutputDir(root);
+            IOUtils.writableOutputDir(binDir);
+        } catch (PackagerException pe) {
+            throw new RuntimeException(pe);
         }
+        AppImageFile.save(root, params);
+
         // create the .exe launchers
         createLauncherForEntryPoint(params);
 
         // copy the jars
         copyApplication(params);
 
         // copy in the needed libraries
         try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
-            Files.copy(is_lib, root.resolve(LIBRARY_NAME));
+            Files.copy(is_lib, binDir.resolve(LIBRARY_NAME));
         }
 
         copyMSVCDLLs();
 
         // create the additional launcher(s), if any

@@ -259,21 +211,22 @@
                     AddLauncherArguments.merge(originalParams, entryPoint));
         }
     }
 
     @Override
-    public void prepareJreFiles() throws IOException {}
+    public void prepareJreFiles(Map<String, ? super Object> params)
+        throws IOException {}
 
     private void copyMSVCDLLs() throws IOException {
         AtomicReference<IOException> ioe = new AtomicReference<>();
         try (Stream<Path> files = Files.list(runtimeDir.resolve("bin"))) {
             files.filter(p -> Pattern.matches(
                     "^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$",
                     p.toFile().getName().toLowerCase()))
                  .forEach(p -> {
                     try {
-                        Files.copy(p, root.resolve((p.toFile().getName())));
+                        Files.copy(p, binDir.resolve((p.toFile().getName())));
                     } catch (IOException e) {
                         ioe.set(e);
                     }
                 });
         }

@@ -282,30 +235,10 @@
         if (e != null) {
             throw e;
         }
     }
 
-    // TODO: do we still need this?
-    private boolean copyMSVCDLLs(String VS_VER) throws IOException {
-        final InputStream REDIST_MSVCR_URL = getResourceAsStream(
-                REDIST_MSVCR.replaceAll("VS_VER", VS_VER));
-        final InputStream REDIST_MSVCP_URL = getResourceAsStream(
-                REDIST_MSVCP.replaceAll("VS_VER", VS_VER));
-
-        if (REDIST_MSVCR_URL != null && REDIST_MSVCP_URL != null) {
-            Files.copy(
-                    REDIST_MSVCR_URL,
-                    root.resolve(REDIST_MSVCR.replaceAll("VS_VER", VS_VER)));
-            Files.copy(
-                    REDIST_MSVCP_URL,
-                    root.resolve(REDIST_MSVCP.replaceAll("VS_VER", VS_VER)));
-            return true;
-        }
-
-        return false;
-    }
-
     private void validateValueAndPut(
             Map<String, String> data, String key,
             BundlerParamInfo<String> param,
             Map<String, ? super Object> params) {
         String value = param.fetchFrom(params);

@@ -318,10 +251,11 @@
         data.put(key, value);
     }
 
     protected void prepareExecutableProperties(
            Map<String, ? super Object> params) throws IOException {
+
         Map<String, String> data = new HashMap<>();
 
         // mapping Java parameters in strings for version resource
         validateValueAndPut(data, "COMPANY_NAME", VENDOR, params);
         validateValueAndPut(data, "FILE_DESCRIPTION", DESCRIPTION, params);

@@ -330,67 +264,53 @@
         validateValueAndPut(data, "LEGAL_COPYRIGHT", COPYRIGHT, params);
         data.put("ORIGINAL_FILENAME", getLauncherName(params));
         validateValueAndPut(data, "PRODUCT_NAME", APP_NAME, params);
         validateValueAndPut(data, "PRODUCT_VERSION", VERSION, params);
 
-        try (Writer w = Files.newBufferedWriter(
-                getConfig_ExecutableProperties(params).toPath(),
-                StandardCharsets.UTF_8)) {
-            String content = preprocessTextResource(
-                    getConfig_ExecutableProperties(params).getName(),
-                    I18N.getString("resource.executable-properties-template"),
-                    EXECUTABLE_PROPERTIES_TEMPLATE, data,
-                    VERBOSE.fetchFrom(params),
-                    RESOURCE_DIR.fetchFrom(params));
-            w.write(content);
-        }
+        createResource(EXECUTABLE_PROPERTIES_TEMPLATE, params)
+                .setCategory(I18N.getString("resource.executable-properties-template"))
+                .setSubstitutionData(data)
+                .saveToFile(getConfig_ExecutableProperties(params));
     }
 
     private void createLauncherForEntryPoint(
-            Map<String, ? super Object> p) throws IOException {
+            Map<String, ? super Object> params) throws IOException {
+
+        File iconTarget = getConfig_AppIcon(params);
+
+        createResource(TEMPLATE_APP_ICON, params)
+                .setCategory("icon")
+                .setExternal(ICON_ICO.fetchFrom(params))
+                .saveToFile(iconTarget);
 
-        File launcherIcon = ICON_ICO.fetchFrom(p);
-        File icon = launcherIcon != null ?
-                launcherIcon : ICON_ICO.fetchFrom(params);
-        File iconTarget = getConfig_AppIcon(p);
-
-        InputStream in = locateResource(
-                APP_NAME.fetchFrom(params) + ".ico",
-                "icon",
-                TEMPLATE_APP_ICON,
-                icon,
-                VERBOSE.fetchFrom(params),
-                RESOURCE_DIR.fetchFrom(params));
-
-        Files.copy(in, iconTarget.toPath(),
-                StandardCopyOption.REPLACE_EXISTING);
+        writeCfgFile(params, root.resolve(
+                getLauncherCfgName(params)).toFile());
 
-        writeCfgFile(p, root.resolve(
-                getLauncherCfgName(p)).toFile(), "$APPDIR\\runtime");
+        prepareExecutableProperties(params);
 
-        prepareExecutableProperties(p);
+        // Copy executable to bin folder
+        Path executableFile = binDir.resolve(getLauncherName(params));
 
-        // Copy executable root folder
-        Path executableFile = root.resolve(getLauncherName(p));
         try (InputStream is_launcher =
-                getResourceAsStream(getLauncherResourceName(p))) {
+                getResourceAsStream(getLauncherResourceName(params))) {
             writeEntry(is_launcher, executableFile);
         }
 
         File launcher = executableFile.toFile();
         launcher.setWritable(true, true);
 
         // Update branding of EXE file
-        if (REBRAND_EXECUTABLE.fetchFrom(p)) {
+        if (REBRAND_EXECUTABLE.fetchFrom(params)) {
             try {
                 String tempDirectory = WindowsDefender.getUserTempDirectory();
                 if (Arguments.CLIOptions.context().userProvidedBuildRoot) {
-                    tempDirectory = TEMP_ROOT.fetchFrom(p).getAbsolutePath();
+                    tempDirectory =
+                            TEMP_ROOT.fetchFrom(params).getAbsolutePath();
                 }
                 if (WindowsDefender.isThereAPotentialWindowsDefenderIssue(
                         tempDirectory)) {
-                    Log.error(MessageFormat.format(I18N.getString(
+                    Log.verbose(MessageFormat.format(I18N.getString(
                             "message.potential.windows.defender.issue"),
                             tempDirectory));
                 }
 
                 launcher.setWritable(true);

@@ -398,27 +318,29 @@
                 if (iconTarget.exists()) {
                     iconSwap(iconTarget.getAbsolutePath(),
                             launcher.getAbsolutePath());
                 }
 
-                File executableProperties = getConfig_ExecutableProperties(p);
+                File executableProperties =
+                        getConfig_ExecutableProperties(params);
 
                 if (executableProperties.exists()) {
                     if (versionSwap(executableProperties.getAbsolutePath(),
                             launcher.getAbsolutePath()) != 0) {
                         throw new RuntimeException(MessageFormat.format(
                                 I18N.getString("error.version-swap"),
                                 executableProperties.getAbsolutePath()));
                     }
                 }
             } finally {
+                executableFile.toFile().setExecutable(true);
                 executableFile.toFile().setReadOnly();
             }
         }
 
         Files.copy(iconTarget.toPath(),
-                root.resolve(APP_NAME.fetchFrom(p) + ".ico"));
+                binDir.resolve(APP_NAME.fetchFrom(params) + ".ico"));
     }
 
     private void copyApplication(Map<String, ? super Object> params)
             throws IOException {
         List<RelativeFileSet> appResourcesList =

@@ -437,8 +359,9 @@
         }
     }
 
     private static native int iconSwap(String iconTarget, String launcher);
 
-    private static native int versionSwap(String executableProperties, String launcher);
+    private static native int versionSwap(String executableProperties,
+            String launcher);
 
 }
< prev index next >