1 /* 2 * Copyright (c) 2012, 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.jpackage.internal; 27 28 import java.io.File; 29 import java.io.IOException; 30 import java.util.*; 31 import java.util.jar.Attributes; 32 import java.util.jar.JarFile; 33 import java.util.jar.Manifest; 34 35 import static jdk.jpackage.internal.StandardBundlerParam.*; 36 37 public class BundleParams { 38 39 final protected Map<String, ? super Object> params; 40 41 // RelativeFileSet 42 public static final String PARAM_APP_RESOURCES = "appResources"; 43 44 // BundlerType 45 public static final String PARAM_TYPE = "type"; 46 47 // String 48 public static final String PARAM_BUNDLE_FORMAT = "bundleFormat"; 49 // String 50 public static final String PARAM_ICON = "icon"; 51 52 // String - Name of bundle file and native launcher 53 public static final String PARAM_NAME = "name"; 54 55 // String - application vendor, used by most of the bundlers 56 public static final String PARAM_VENDOR = "vendor"; 57 58 // String - email name and email, only used for debian */ 59 public static final String PARAM_EMAIL = "email"; 60 61 /* String - Copyright. Used on Mac */ 62 public static final String PARAM_COPYRIGHT = "copyright"; 63 64 // String - GUID on windows for MSI, CFBundleIdentifier on Mac 65 // If not compatible with requirements then bundler either do not bundle 66 // or autogenerate 67 public static final String PARAM_IDENTIFIER = "identifier"; 68 69 /* boolean - shortcut preferences */ 70 public static final String PARAM_SHORTCUT = "shortcutHint"; 71 // boolean - menu shortcut preference 72 public static final String PARAM_MENU = "menuHint"; 73 74 // String - Application version. Format may differ for different bundlers 75 public static final String PARAM_VERSION = "appVersion"; 76 77 // String - Application category. Used at least on Mac/Linux. 78 // Value is platform specific 79 public static final String PARAM_CATEGORY = "applicationCategory"; 80 81 // String - Optional short application 82 public static final String PARAM_TITLE = "title"; 83 84 // String - Optional application description. Used by MSI and on Linux 85 public static final String PARAM_DESCRIPTION = "description"; 86 87 // String - License type. Needed on Linux (rpm) 88 public static final String PARAM_LICENSE_TYPE = "licenseType"; 89 90 // String - File with license. Format is OS/bundler specific 91 public static final String PARAM_LICENSE_FILE = "licenseFile"; 92 93 // String Main application class. 94 // Not used directly but used to derive default values 95 public static final String PARAM_APPLICATION_CLASS = "applicationClass"; 96 97 // boolean - Adds a dialog to let the user choose a directory 98 // where the product will be installed. 99 public static final String PARAM_INSTALLDIR_CHOOSER = "installdirChooser"; 100 101 /** 102 * create a new bundle with all default values 103 */ 104 public BundleParams() { 105 params = new HashMap<>(); 106 } 107 108 /** 109 * Create a bundle params with a copy of the params 110 * @param params map of initial parameters to be copied in. 111 */ 112 public BundleParams(Map<String, ?> params) { 113 this.params = new HashMap<>(params); 114 } 115 116 public void addAllBundleParams(Map<String, ? super Object> p) { 117 params.putAll(p); 118 } 119 120 public <C> C fetchParam(BundlerParamInfo<C> paramInfo) { 121 return paramInfo.fetchFrom(params); 122 } 123 124 @SuppressWarnings("unchecked") 125 public <C> C fetchParamWithDefault( 126 Class<C> klass, C defaultValue, String... keys) { 127 for (String key : keys) { 128 Object o = params.get(key); 129 if (klass.isInstance(o)) { 130 return (C) o; 131 } else if (params.containsKey(key) && o == null) { 132 return null; 133 } else if (o != null) { 134 Log.debug("Bundle param " + key + " is not type " + klass); 135 } 136 } 137 return defaultValue; 138 } 139 140 public <C> C fetchParam(Class<C> klass, String... keys) { 141 return fetchParamWithDefault(klass, null, keys); 142 } 143 144 // NOTE: we do not care about application parameters here 145 // as they will be embeded into jar file manifest and 146 // java launcher will take care of them! 147 148 public Map<String, ? super Object> getBundleParamsAsMap() { 149 return new HashMap<>(params); 150 } 151 152 public void setJvmargs(List<String> jvmargs) { 153 putUnlessNullOrEmpty(JVM_OPTIONS.getID(), jvmargs); 154 } 155 156 public void setArguments(List<String> arguments) { 157 putUnlessNullOrEmpty(ARGUMENTS.getID(), arguments); 158 } 159 160 public void setAddModules(String value) { 161 putUnlessNull(StandardBundlerParam.ADD_MODULES.getID(), value); 162 } 163 164 public void setLimitModules(String value) { 165 putUnlessNull(StandardBundlerParam.LIMIT_MODULES.getID(), value); 166 } 167 168 public void setStripNativeCommands(boolean value) { 169 putUnlessNull(StandardBundlerParam.STRIP_NATIVE_COMMANDS.getID(), 170 value); 171 } 172 173 public void setModulePath(String value) { 174 putUnlessNull(StandardBundlerParam.MODULE_PATH.getID(), value); 175 } 176 177 public void setMainModule(String value) { 178 putUnlessNull(StandardBundlerParam.MODULE.getID(), value); 179 } 180 181 public void setDebug(String value) { 182 putUnlessNull(JLinkBundlerHelper.DEBUG.getID(), value); 183 } 184 185 public String getApplicationID() { 186 return fetchParam(IDENTIFIER); 187 } 188 189 public String getPreferencesID() { 190 return fetchParam(PREFERENCES_ID); 191 } 192 193 public String getTitle() { 194 return fetchParam(TITLE); 195 } 196 197 public void setTitle(String title) { 198 putUnlessNull(PARAM_TITLE, title); 199 } 200 201 public String getApplicationClass() { 202 return fetchParam(MAIN_CLASS); 203 } 204 205 public void setApplicationClass(String applicationClass) { 206 putUnlessNull(PARAM_APPLICATION_CLASS, applicationClass); 207 } 208 209 public String getAppVersion() { 210 return fetchParam(VERSION); 211 } 212 213 public void setAppVersion(String version) { 214 putUnlessNull(PARAM_VERSION, version); 215 } 216 217 public String getDescription() { 218 return fetchParam(DESCRIPTION); 219 } 220 221 public void setDescription(String s) { 222 putUnlessNull(PARAM_DESCRIPTION, s); 223 } 224 225 public void setInstalldirChooser(Boolean b) { 226 putUnlessNull(PARAM_INSTALLDIR_CHOOSER, b); 227 } 228 229 public String getName() { 230 return fetchParam(APP_NAME); 231 } 232 233 public void setName(String name) { 234 putUnlessNull(PARAM_NAME, name); 235 } 236 237 @SuppressWarnings("deprecation") 238 public BundlerType getType() { 239 return fetchParam(BundlerType.class, PARAM_TYPE); 240 } 241 242 @SuppressWarnings("deprecation") 243 public void setType(BundlerType type) { 244 putUnlessNull(PARAM_TYPE, type); 245 } 246 247 public String getBundleFormat() { 248 return fetchParam(String.class, PARAM_BUNDLE_FORMAT); 249 } 250 251 public void setBundleFormat(String t) { 252 putUnlessNull(PARAM_BUNDLE_FORMAT, t); 253 } 254 255 public boolean getVerbose() { 256 return fetchParam(VERBOSE); 257 } 258 259 public List<String> getJvmargs() { 260 return JVM_OPTIONS.fetchFrom(params); 261 } 262 263 public List<String> getArguments() { 264 return ARGUMENTS.fetchFrom(params); 265 } 266 267 public jdk.jpackage.internal.RelativeFileSet getAppResource() { 268 return fetchParam(APP_RESOURCES); 269 } 270 271 public void setAppResource(jdk.jpackage.internal.RelativeFileSet fs) { 272 putUnlessNull(PARAM_APP_RESOURCES, fs); 273 } 274 275 public void setAppResourcesList( 276 List<jdk.jpackage.internal.RelativeFileSet> rfs) { 277 putUnlessNull(APP_RESOURCES_LIST.getID(), rfs); 278 } 279 280 public String getApplicationCategory() { 281 return fetchParam(CATEGORY); 282 } 283 284 public void setApplicationCategory(String category) { 285 putUnlessNull(PARAM_CATEGORY, category); 286 } 287 288 public String getMainClassName() { 289 String applicationClass = getApplicationClass(); 290 291 if (applicationClass == null) { 292 return null; 293 } 294 295 int idx = applicationClass.lastIndexOf("."); 296 if (idx >= 0) { 297 return applicationClass.substring(idx+1); 298 } 299 return applicationClass; 300 } 301 302 public String getCopyright() { 303 return fetchParam(COPYRIGHT); 304 } 305 306 public void setCopyright(String c) { 307 putUnlessNull(PARAM_COPYRIGHT, c); 308 } 309 310 public String getIdentifier() { 311 return fetchParam(IDENTIFIER); 312 } 313 314 public void setIdentifier(String s) { 315 putUnlessNull(PARAM_IDENTIFIER, s); 316 } 317 318 private String mainJar = null; 319 320 // assuming that application was packaged according to the rules 321 // we must have application jar, i.e. jar where we embed launcher 322 // and have main application class listed as main class! 323 // If there are more than one, or none - it will be treated as 324 // deployment error 325 // 326 // Note we look for both JavaFX executable jars and regular executable jars 327 // As long as main "application" entry point is the same it is main class 328 // (i.e. for FX jar we will use JavaFX manifest entry ...) 329 public String getMainApplicationJar() { 330 jdk.jpackage.internal.RelativeFileSet appResources = getAppResource(); 331 if (mainJar != null) { 332 if (getApplicationClass() == null) try { 333 if (appResources != null) { 334 File srcdir = appResources.getBaseDirectory(); 335 JarFile jf = new JarFile(new File(srcdir, mainJar)); 336 Manifest m = jf.getManifest(); 337 Attributes attrs = (m != null) ? 338 m.getMainAttributes() : null; 339 if (attrs != null) { 340 setApplicationClass( 341 attrs.getValue(Attributes.Name.MAIN_CLASS)); 342 } 343 } 344 } catch (IOException ignore) { 345 } 346 return mainJar; 347 } 348 349 String applicationClass = getApplicationClass(); 350 351 if (appResources == null || applicationClass == null) { 352 return null; 353 } 354 File srcdir = appResources.getBaseDirectory(); 355 for (String fname : appResources.getIncludedFiles()) { 356 JarFile jf; 357 try { 358 jf = new JarFile(new File(srcdir, fname)); 359 Manifest m = jf.getManifest(); 360 Attributes attrs = (m != null) ? m.getMainAttributes() : null; 361 if (attrs != null) { 362 boolean javaMain = applicationClass.equals( 363 attrs.getValue(Attributes.Name.MAIN_CLASS)); 364 365 if (javaMain) { 366 mainJar = fname; 367 return mainJar; 368 } 369 } 370 } catch (IOException ignore) { 371 } 372 } 373 return null; 374 } 375 376 public String getVendor() { 377 return fetchParam(VENDOR); 378 } 379 380 public void setVendor(String vendor) { 381 putUnlessNull(PARAM_VENDOR, vendor); 382 } 383 384 public String getEmail() { 385 return fetchParam(String.class, PARAM_EMAIL); 386 } 387 388 public void setEmail(String email) { 389 putUnlessNull(PARAM_EMAIL, email); 390 } 391 392 public void putUnlessNull(String param, Object value) { 393 if (value != null) { 394 params.put(param, value); 395 } 396 } 397 398 public void putUnlessNullOrEmpty(String param, Collection<?> value) { 399 if (value != null && !value.isEmpty()) { 400 params.put(param, value); 401 } 402 } 403 404 public void putUnlessNullOrEmpty(String param, Map<?,?> value) { 405 if (value != null && !value.isEmpty()) { 406 params.put(param, value); 407 } 408 } 409 410 }