1 /* 2 * Copyright (c) 2012, 2018, 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.jpackager.internal.linux; 27 28 import jdk.jpackager.internal.AbstractImageBundler; 29 import jdk.jpackager.internal.BundlerParamInfo; 30 import jdk.jpackager.internal.ConfigException; 31 import jdk.jpackager.internal.IOUtils; 32 import jdk.jpackager.internal.Log; 33 import jdk.jpackager.internal.Platform; 34 import jdk.jpackager.internal.RelativeFileSet; 35 import jdk.jpackager.internal.StandardBundlerParam; 36 import jdk.jpackager.internal.Arguments; 37 import jdk.jpackager.internal.UnsupportedPlatformException; 38 import jdk.jpackager.internal.bundlers.BundleParams; 39 import jdk.jpackager.internal.builders.linux.LinuxAppImageBuilder; 40 import jdk.jpackager.internal.resources.linux.LinuxResources; 41 import jdk.jpackager.internal.JLinkBundlerHelper; 42 import jdk.jpackager.internal.builders.AbstractAppImageBuilder; 43 44 import java.io.File; 45 import java.io.IOException; 46 import java.net.MalformedURLException; 47 import java.net.URL; 48 import java.text.MessageFormat; 49 import java.util.Arrays; 50 import java.util.Collection; 51 import java.util.Map; 52 import java.util.ResourceBundle; 53 54 import static jdk.jpackager.internal.StandardBundlerParam.*; 55 56 public class LinuxAppBundler extends AbstractImageBundler { 57 58 private static final ResourceBundle I18N = ResourceBundle.getBundle( 59 "jdk.jpackager.internal.resources.linux.LinuxAppBundler"); 60 61 protected static final String LINUX_BUNDLER_PREFIX = 62 BUNDLER_PREFIX + "linux" + File.separator; 63 private static final String EXECUTABLE_NAME = "JavaAppLauncher"; 64 65 public static final BundlerParamInfo<File> ICON_PNG = 66 new StandardBundlerParam<>( 67 I18N.getString("param.icon-png.name"), 68 I18N.getString("param.icon-png.description"), 69 "icon.png", 70 File.class, 71 params -> { 72 File f = ICON.fetchFrom(params); 73 if (f != null && !f.getName().toLowerCase().endsWith(".png")) { 74 Log.error(MessageFormat.format( 75 I18N.getString("message.icon-not-png"), f)); 76 return null; 77 } 78 return f; 79 }, 80 (s, p) -> new File(s)); 81 82 public static final BundlerParamInfo<String> LINUX_INSTALL_DIR = 83 new StandardBundlerParam<>( 84 I18N.getString("param.linux-install-dir.name"), 85 I18N.getString("param.linux-install-dir.description"), 86 "linux-install-dir", 87 String.class, 88 params -> { 89 String dir = INSTALL_DIR.fetchFrom(params); 90 if (dir != null) { 91 if (dir.endsWith("/")) { 92 dir = dir.substring(0, dir.length()-1); 93 } 94 return dir; 95 } 96 return "/opt"; 97 }, 98 (s, p) -> s 99 ); 100 101 public static final BundlerParamInfo<String> LINUX_PACKAGE_DEPENDENCIES = 102 new StandardBundlerParam<>( 103 I18N.getString("param.linux-package-dependencies.name"), 104 I18N.getString("param.linux-package-dependencies.description"), 105 Arguments.CLIOptions.LINUX_PACKAGE_DEPENDENCIES.getId(), 106 String.class, 107 params -> { 108 return ""; 109 }, 110 (s, p) -> s 111 ); 112 113 @Override 114 public boolean validate(Map<String, ? super Object> p) 115 throws UnsupportedPlatformException, ConfigException { 116 try { 117 if (p == null) throw new ConfigException( 118 I18N.getString("error.parameters-null"), 119 I18N.getString("error.parameters-null.advice")); 120 121 return doValidate(p); 122 } catch (RuntimeException re) { 123 if (re.getCause() instanceof ConfigException) { 124 throw (ConfigException) re.getCause(); 125 } else { 126 throw new ConfigException(re); 127 } 128 } 129 } 130 131 //used by chained bundlers to reuse validation logic 132 boolean doValidate(Map<String, ? super Object> p) 133 throws UnsupportedPlatformException, ConfigException { 134 if (Platform.getPlatform() != Platform.LINUX) { 135 throw new UnsupportedPlatformException(); 136 } 137 138 imageBundleValidation(p); 139 140 return true; 141 } 142 143 // it is static for the sake of sharing with "installer" bundlers 144 // that may skip calls to validate/bundle in this class! 145 public static File getRootDir(File outDir, Map<String, ? super Object> p) { 146 return new File(outDir, APP_FS_NAME.fetchFrom(p)); 147 } 148 149 public static String getLauncherCfgName(Map<String, ? super Object> p) { 150 return "app/" + APP_FS_NAME.fetchFrom(p) +".cfg"; 151 } 152 153 File doBundle(Map<String, ? super Object> p, File outputDirectory, 154 boolean dependentTask) { 155 if (Arguments.CREATE_JRE_INSTALLER.fetchFrom(p)) { 156 return doJreBundle(p, outputDirectory, dependentTask); 157 } else { 158 return doAppBundle(p, outputDirectory, dependentTask); 159 } 160 } 161 162 private File doJreBundle(Map<String, ? super Object> p, 163 File outputDirectory, boolean dependentTask) { 164 try { 165 File rootDirectory = createRoot(p, outputDirectory, dependentTask, 166 APP_FS_NAME.fetchFrom(p), "linuxapp-image-builder"); 167 AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder( 168 APP_NAME.fetchFrom(p), outputDirectory.toPath()); 169 File predefined = PREDEFINED_RUNTIME_IMAGE.fetchFrom(p); 170 if (predefined == null ) { 171 JLinkBundlerHelper.generateServerJre(p, appBuilder); 172 } else { 173 return predefined; 174 } 175 return rootDirectory; 176 } catch (Exception ex) { 177 Log.error("Exception: "+ex); 178 Log.debug(ex); 179 return null; 180 } 181 } 182 183 private File doAppBundle(Map<String, ? super Object> p, 184 File outputDirectory, boolean dependentTask) { 185 try { 186 File rootDirectory = createRoot(p, outputDirectory, dependentTask, 187 APP_FS_NAME.fetchFrom(p), "linuxapp-image-builder"); 188 AbstractAppImageBuilder appBuilder = new LinuxAppImageBuilder(p, 189 outputDirectory.toPath()); 190 if (PREDEFINED_RUNTIME_IMAGE.fetchFrom(p) == null ) { 191 JLinkBundlerHelper.execute(p, appBuilder); 192 } else { 193 StandardBundlerParam.copyPredefinedRuntimeImage(p, appBuilder); 194 } 195 return rootDirectory; 196 } catch (Exception ex) { 197 Log.error("Exception: "+ex); 198 Log.debug(ex); 199 return null; 200 } 201 } 202 203 @Override 204 public String getName() { 205 return I18N.getString("bundler.name"); 206 } 207 208 @Override 209 public String getDescription() { 210 return I18N.getString("bundler.description"); 211 } 212 213 @Override 214 public String getID() { 215 return "linux.app"; 216 } 217 218 @Override 219 public String getBundleType() { 220 return "IMAGE"; 221 } 222 223 @Override 224 public Collection<BundlerParamInfo<?>> getBundleParameters() { 225 return getAppBundleParameters(); 226 } 227 228 public static Collection<BundlerParamInfo<?>> getAppBundleParameters() { 229 return Arrays.asList( 230 APP_NAME, 231 APP_RESOURCES, 232 ARGUMENTS, 233 CLASSPATH, 234 JVM_OPTIONS, 235 JVM_PROPERTIES, 236 MAIN_CLASS, 237 MAIN_JAR, 238 PREFERENCES_ID, 239 VERSION, 240 VERBOSE 241 ); 242 } 243 244 @Override 245 public File execute(Map<String, ? super Object> params, 246 File outputParentDir) { 247 return doBundle(params, outputParentDir, false); 248 } 249 250 @Override 251 public boolean supported() { 252 return (Platform.getPlatform() == Platform.LINUX); 253 } 254 }