|
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.text.MessageFormat; |
|
34 import java.util.HashMap; |
|
35 import java.util.List; |
|
36 import java.util.Map; |
|
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 public static final BundlerParamInfo<File> ICON_PNG = |
|
49 new StandardBundlerParam<>( |
|
50 "icon.png", |
|
51 File.class, |
|
52 params -> { |
|
53 File f = ICON.fetchFrom(params); |
|
54 if (f != null && !f.getName().toLowerCase().endsWith(".png")) { |
|
55 Log.error(MessageFormat.format(I18N.getString( |
|
56 "message.icon-not-png"), f)); |
|
57 return null; |
|
58 } |
|
59 return f; |
|
60 }, |
|
61 (s, p) -> new File(s)); |
|
62 |
|
63 private static ApplicationLayout createAppLayout(Map<String, Object> params, |
|
64 Path imageOutDir) { |
|
65 return ApplicationLayout.linuxAppImage().resolveAt( |
|
66 imageOutDir.resolve(APP_NAME.fetchFrom(params))); |
|
67 } |
|
68 |
|
69 public LinuxAppImageBuilder(Map<String, Object> params, Path imageOutDir) |
|
70 throws IOException { |
|
71 super(params, createAppLayout(params, imageOutDir).runtimeDirectory()); |
|
72 |
|
73 appLayout = createAppLayout(params, imageOutDir); |
|
74 } |
|
75 |
|
76 private void writeEntry(InputStream in, Path dstFile) throws IOException { |
|
77 Files.createDirectories(dstFile.getParent()); |
|
78 Files.copy(in, dstFile); |
|
79 } |
|
80 |
|
81 public static String getLauncherName(Map<String, ? super Object> params) { |
|
82 return APP_NAME.fetchFrom(params); |
|
83 } |
|
84 |
|
85 private Path getLauncherCfgPath(Map<String, ? super Object> params) { |
|
86 return appLayout.appDirectory().resolve( |
|
87 APP_NAME.fetchFrom(params) + ".cfg"); |
|
88 } |
|
89 |
|
90 @Override |
|
91 public Path getAppDir() { |
|
92 return appLayout.appDirectory(); |
|
93 } |
|
94 |
|
95 @Override |
|
96 public Path getAppModsDir() { |
|
97 return appLayout.appModsDirectory(); |
|
98 } |
|
99 |
|
100 @Override |
|
101 protected String getCfgAppDir() { |
|
102 return Path.of("$ROOTDIR").resolve( |
|
103 ApplicationLayout.linuxAppImage().appDirectory()).toString() |
|
104 + File.separator; |
|
105 } |
|
106 |
|
107 @Override |
|
108 protected String getCfgRuntimeDir() { |
|
109 return Path.of("$ROOTDIR").resolve( |
|
110 ApplicationLayout.linuxAppImage().runtimeDirectory()).toString(); |
|
111 } |
|
112 |
|
113 @Override |
|
114 public void prepareApplicationFiles(Map<String, ? super Object> params) |
|
115 throws IOException { |
|
116 Map<String, ? super Object> originalParams = new HashMap<>(params); |
|
117 |
|
118 appLayout.roots().stream().forEach(dir -> { |
|
119 try { |
|
120 IOUtils.writableOutputDir(dir); |
|
121 } catch (PackagerException pe) { |
|
122 throw new RuntimeException(pe); |
|
123 } |
|
124 }); |
|
125 |
|
126 // create the primary launcher |
|
127 createLauncherForEntryPoint(params); |
|
128 |
|
129 // Copy library to the launcher folder |
|
130 try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) { |
|
131 writeEntry(is_lib, appLayout.dllDirectory().resolve(LIBRARY_NAME)); |
|
132 } |
|
133 |
|
134 // create the additional launchers, if any |
|
135 List<Map<String, ? super Object>> entryPoints |
|
136 = StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); |
|
137 for (Map<String, ? super Object> entryPoint : entryPoints) { |
|
138 createLauncherForEntryPoint( |
|
139 AddLauncherArguments.merge(originalParams, entryPoint)); |
|
140 } |
|
141 |
|
142 // Copy class path entries to Java folder |
|
143 copyApplication(params); |
|
144 |
|
145 // Copy icon to Resources folder |
|
146 copyIcon(params); |
|
147 } |
|
148 |
|
149 @Override |
|
150 public void prepareJreFiles(Map<String, ? super Object> params) |
|
151 throws IOException {} |
|
152 |
|
153 private void createLauncherForEntryPoint( |
|
154 Map<String, ? super Object> params) throws IOException { |
|
155 // Copy executable to launchers folder |
|
156 Path executableFile = appLayout.launchersDirectory().resolve(getLauncherName(params)); |
|
157 try (InputStream is_launcher = |
|
158 getResourceAsStream("jpackageapplauncher")) { |
|
159 writeEntry(is_launcher, executableFile); |
|
160 } |
|
161 |
|
162 executableFile.toFile().setExecutable(true, false); |
|
163 executableFile.toFile().setWritable(true, true); |
|
164 |
|
165 writeCfgFile(params, getLauncherCfgPath(params).toFile()); |
|
166 } |
|
167 |
|
168 private void copyIcon(Map<String, ? super Object> params) |
|
169 throws IOException { |
|
170 |
|
171 Path iconTarget = appLayout.destktopIntegrationDirectory().resolve( |
|
172 APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of( |
|
173 DEFAULT_ICON))); |
|
174 |
|
175 createResource(DEFAULT_ICON, params) |
|
176 .setCategory("icon") |
|
177 .setExternal(ICON_PNG.fetchFrom(params)) |
|
178 .saveToFile(iconTarget); |
|
179 } |
|
180 |
|
181 private void copyApplication(Map<String, ? super Object> params) |
|
182 throws IOException { |
|
183 for (RelativeFileSet appResources : |
|
184 APP_RESOURCES_LIST.fetchFrom(params)) { |
|
185 if (appResources == null) { |
|
186 throw new RuntimeException("Null app resources?"); |
|
187 } |
|
188 File srcdir = appResources.getBaseDirectory(); |
|
189 for (String fname : appResources.getIncludedFiles()) { |
|
190 copyEntry(appLayout.appDirectory(), srcdir, fname); |
|
191 } |
|
192 } |
|
193 } |
|
194 |
|
195 } |