1 /* 2 * Copyright (c) 2015, 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.File; 29 import java.io.IOException; 30 import java.io.InputStream; 31 import java.nio.file.Files; 32 import java.nio.file.Path; 33 import java.util.HashMap; 34 import java.util.List; 35 import java.util.Map; 36 import static jdk.incubator.jpackage.internal.LinuxAppBundler.ICON_PNG; 37 import static jdk.incubator.jpackage.internal.OverridableResource.createResource; 38 39 import static jdk.incubator.jpackage.internal.StandardBundlerParam.*; 40 41 public class LinuxAppImageBuilder extends AbstractAppImageBuilder { 42 43 private static final String LIBRARY_NAME = "libapplauncher.so"; 44 final static String DEFAULT_ICON = "java32.png"; 45 46 private final ApplicationLayout appLayout; 47 48 private static ApplicationLayout createAppLayout(Map<String, Object> params, 49 Path imageOutDir) { 50 return ApplicationLayout.linuxAppImage().resolveAt( 51 imageOutDir.resolve(APP_NAME.fetchFrom(params))); 52 } 53 54 public LinuxAppImageBuilder(Map<String, Object> params, Path imageOutDir) 55 throws IOException { 56 super(params, createAppLayout(params, imageOutDir).runtimeDirectory()); 57 58 appLayout = createAppLayout(params, imageOutDir); 59 } 60 61 private void writeEntry(InputStream in, Path dstFile) throws IOException { 62 Files.createDirectories(dstFile.getParent()); 63 Files.copy(in, dstFile); 64 } 65 66 public static String getLauncherName(Map<String, ? super Object> params) { 67 return APP_NAME.fetchFrom(params); 68 } 69 70 private Path getLauncherCfgPath(Map<String, ? super Object> params) { 71 return appLayout.appDirectory().resolve( 72 APP_NAME.fetchFrom(params) + ".cfg"); 73 } 74 75 @Override 76 public Path getAppDir() { 77 return appLayout.appDirectory(); 78 } 79 80 @Override 81 public Path getAppModsDir() { 82 return appLayout.appModsDirectory(); 83 } 84 85 @Override 86 protected String getCfgAppDir() { 87 return Path.of("$ROOTDIR").resolve( 88 ApplicationLayout.linuxAppImage().appDirectory()).toString() 89 + File.separator; 90 } 91 92 @Override 93 protected String getCfgRuntimeDir() { 94 return Path.of("$ROOTDIR").resolve( 95 ApplicationLayout.linuxAppImage().runtimeDirectory()).toString(); 96 } 97 98 @Override 99 public void prepareApplicationFiles(Map<String, ? super Object> params) 100 throws IOException { 101 appLayout.roots().stream().forEach(dir -> { 102 try { 103 IOUtils.writableOutputDir(dir); 104 } catch (PackagerException pe) { 105 throw new RuntimeException(pe); 106 } 107 }); 108 109 // create the primary launcher 110 createLauncherForEntryPoint(params, null); 111 112 // Copy library to the launcher folder 113 try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) { 114 writeEntry(is_lib, appLayout.dllDirectory().resolve(LIBRARY_NAME)); 115 } 116 117 // create the additional launchers, if any 118 List<Map<String, ? super Object>> entryPoints 119 = StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); 120 for (Map<String, ? super Object> entryPoint : entryPoints) { 121 createLauncherForEntryPoint(AddLauncherArguments.merge(params, 122 entryPoint, ICON.getID(), ICON_PNG.getID()), params); 123 } 124 125 // Copy class path entries to Java folder 126 copyApplication(params); 127 } 128 129 @Override 130 public void prepareJreFiles(Map<String, ? super Object> params) 131 throws IOException {} 132 133 private void createLauncherForEntryPoint(Map<String, ? super Object> params, 134 Map<String, ? super Object> mainParams) throws IOException { 135 // Copy executable to launchers folder 136 Path executableFile = appLayout.launchersDirectory().resolve(getLauncherName(params)); 137 try (InputStream is_launcher = 138 getResourceAsStream("jpackageapplauncher")) { 139 writeEntry(is_launcher, executableFile); 140 } 141 142 executableFile.toFile().setExecutable(true, false); 143 executableFile.toFile().setWritable(true, true); 144 145 writeCfgFile(params, getLauncherCfgPath(params).toFile()); 146 147 var iconResource = createIconResource(DEFAULT_ICON, ICON_PNG, params, 148 mainParams); 149 if (iconResource != null) { 150 Path iconTarget = appLayout.destktopIntegrationDirectory().resolve( 151 APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of( 152 DEFAULT_ICON))); 153 iconResource.saveToFile(iconTarget); 154 } 155 } 156 157 private void copyApplication(Map<String, ? super Object> params) 158 throws IOException { 159 for (RelativeFileSet appResources : 160 APP_RESOURCES_LIST.fetchFrom(params)) { 161 if (appResources == null) { 162 throw new RuntimeException("Null app resources?"); 163 } 164 File srcdir = appResources.getBaseDirectory(); 165 for (String fname : appResources.getIncludedFiles()) { 166 copyEntry(appLayout.appDirectory(), srcdir, fname); 167 } 168 } 169 } 170 171 }