1 /*
   2  * Copyright (c) 2011, 2016, 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 com.sun.javafx.tools.packager;
  27 
  28 import com.oracle.tools.packager.*;
  29 import com.oracle.tools.packager.RelativeFileSet;
  30 import com.oracle.tools.packager.jnlp.JNLPBundler;
  31 import com.sun.javafx.tools.ant.Callback;
  32 import com.sun.javafx.tools.packager.bundlers.*;
  33 import com.sun.javafx.tools.packager.bundlers.Bundler.BundleType;
  34 import java.io.File;
  35 import java.util.ArrayList;
  36 import java.util.Arrays;
  37 import java.util.Collection;
  38 import java.util.LinkedHashMap;
  39 import java.util.LinkedHashSet;
  40 import java.util.LinkedList;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.Set;
  44 import java.util.TreeMap;
  45 import java.util.TreeSet;
  46 
  47 import static com.oracle.tools.packager.jnlp.JNLPBundler.*;
  48 
  49 public class DeployParams extends CommonParams {
  50     public enum RunMode {
  51         WEBSTART, EMBEDDED, STANDALONE, ALL
  52     }
  53 
  54     final List<RelativeFileSet> resources = new ArrayList<>();
  55 
  56     String id;
  57     String title;
  58     String vendor;
  59     String email;
  60     String description;
  61     String category;
  62     String licenseType;
  63     String copyright;
  64     String version;
  65     Boolean systemWide;
  66     Boolean serviceHint;
  67     Boolean signBundle;
  68     Boolean installdirChooser;
  69 
  70     String applicationClass;
  71     String preloader;
  72 
  73     List<Param> params;
  74     List<HtmlParam> htmlParams;
  75     List<String> arguments; //unnamed arguments
  76 
  77     // Java 9 modules support
  78     Set<String> addModules = new LinkedHashSet<>();
  79     Set<String> limitModules = new LinkedHashSet<>();
  80     boolean detectModules = false;
  81     boolean stripExecutables = false;
  82     String modulePath;
  83     String jdkModulePath;
  84 
  85     int width;
  86     int height;
  87     String embeddedWidth = null;
  88     String embeddedHeight = null;
  89 
  90     String appName;
  91     String codebase;
  92 
  93     boolean embedJNLP = true;
  94     @Deprecated final boolean embedCertificates = false;
  95     boolean allPermissions = false;
  96     String updateMode = "background";
  97     boolean isExtension = false;
  98     boolean isSwingApp = false;
  99 
 100     Boolean needShortcut = null;
 101     Boolean needMenu = null;
 102     Boolean needInstall = null;
 103 
 104     String outfile;
 105     //if true then we cobundle js and image files needed
 106     // for web deployment with the application
 107     boolean includeDT;
 108 
 109     String placeholder = "'javafx-app-placeholder'";
 110     String appId = null;
 111 
 112     // didn't have a setter...
 113     boolean offlineAllowed = true;
 114 
 115     List<JSCallback> callbacks;
 116 
 117     //list of HTML templates to process
 118     List<Template> templates = new LinkedList<>();
 119 
 120     String jrePlatform = "1.8+";
 121     String fxPlatform = PackagerLib.JAVAFX_VERSION+"+";
 122     File javaRuntimeToUse = null;
 123     boolean javaRuntimeWasSet = false;
 124 
 125     //list of jvm args (in theory string can contain spaces and need to be escaped
 126     List<String> jvmargs = new LinkedList<>();
 127     Map<String, String> jvmUserArgs = new LinkedHashMap<>();
 128 
 129     //list of jvm properties (can also be passed as VM args
 130     // but keeping them separate make it a bit more convinient for JNLP generation)
 131     Map<String, String> properties = new LinkedHashMap<>();
 132 
 133     // raw arguments to the bundler
 134     Map<String, ? super Object> bundlerArguments = new LinkedHashMap<>();
 135 
 136     String fallbackApp = null;
 137 
 138     public void setJavaRuntimeSource(File src) {
 139         javaRuntimeToUse = src;
 140         javaRuntimeWasSet = true;
 141     }
 142 
 143     public void setCodebase(String codebase) {
 144         this.codebase = codebase;
 145     }
 146 
 147     public void setId(String id) {
 148         this.id = id;
 149     }
 150 
 151     public void setCategory(String category) {
 152         this.category = category;
 153     }
 154 
 155     public void setLicenseType(String licenseType) {
 156         this.licenseType = licenseType;
 157     }
 158 
 159     public void setCopyright(String copyright) {
 160         this.copyright = copyright;
 161     }
 162 
 163     public void setVersion(String version) {
 164         this.version = version;
 165     }
 166 
 167     public void setSystemWide(Boolean systemWide) {
 168         this.systemWide = systemWide;
 169     }
 170 
 171     public void setServiceHint(Boolean serviceHint) {
 172         this.serviceHint = serviceHint;
 173     }
 174 
 175     public void setInstalldirChooser(Boolean installdirChooser) {
 176         this.installdirChooser = installdirChooser;
 177     }
 178 
 179     public void setSignBundle(Boolean signBundle) {
 180         this.signBundle = signBundle;
 181     }
 182 
 183     public void setJRE(String v) {
 184         jrePlatform = v;
 185     }
 186 
 187     public void setSwingAppWithEmbeddedJavaFX(boolean v) {
 188         isSwingApp = v;
 189     }
 190 
 191     public void setNeedInstall(boolean b) {
 192         needInstall = b;
 193     }
 194 
 195     public void setOfflineAllowed(boolean b) {
 196         offlineAllowed = b;
 197     }
 198 
 199     public void setNeedShortcut(Boolean b) {
 200         needShortcut = b;
 201     }
 202 
 203     public void setNeedMenu(Boolean b) {
 204         needMenu = b;
 205     }
 206 
 207     public void setEmbeddedDimensions(String w, String h) {
 208         embeddedWidth = w;
 209         embeddedHeight = h;
 210     }
 211 
 212     public void setFallback(String v) {
 213         if (v == null) {
 214             return;
 215         }
 216 
 217         if ("none".equals(v) || "null".equals(v)) {
 218             fallbackApp = null;
 219         } else {
 220             fallbackApp = v;
 221         }
 222     }
 223 
 224     public void setJavafx(String v) {
 225         fxPlatform = v;
 226     }
 227 
 228     public void addJvmArg(String v) {
 229         jvmargs.add(v);
 230     }
 231 
 232     public void addJvmUserArg(String n, String v) {
 233         jvmUserArgs.put(n, v);
 234     }
 235 
 236     public void addJvmProperty(String n, String v) {
 237         properties.put(n, v);
 238     }
 239 
 240     public void setAllPermissions(boolean allPermissions) {
 241         this.allPermissions = allPermissions;
 242     }
 243 
 244     public void setAppName(String appName) {
 245         this.appName = appName;
 246     }
 247 
 248     public void setArguments(List<String> args) {
 249         this.arguments = args;
 250     }
 251 
 252     public void addAddModule(String module) {
 253         addModules.add(module);
 254     }
 255 
 256     public void addLimitModule(String module) {
 257         limitModules.add(module);
 258     }
 259 
 260     public void setModulePath(String value) {
 261         this.modulePath = value;
 262     }
 263 
 264     public void setJdkModulePath(String value) {
 265         this.jdkModulePath = value;
 266     }
 267 
 268     public void setDetectModules(boolean value) {
 269         this.detectModules = value;
 270     }
 271 
 272     public void setStripExecutables(boolean value) {
 273         this.stripExecutables = value;
 274     }
 275 
 276     public void setDescription(String description) {
 277         this.description = description;
 278     }
 279 
 280     public void setEmbedJNLP(boolean embedJNLP) {
 281         this.embedJNLP = embedJNLP;
 282     }
 283 
 284     @Deprecated
 285     public void setEmbedCertifcates(boolean v) {
 286         if (v) {
 287             System.out.println("JavaFX Packager no longer supports embedding certificates in JNLP files.  Setting will be ignored.");
 288         }
 289     }
 290 
 291     public void setPlaceholder(String p) {
 292         placeholder = p;
 293     }
 294 
 295     public void setAppId(String id) {
 296         appId = id;
 297     }
 298 
 299     public void setHeight(int height) {
 300         this.height = height;
 301     }
 302 
 303     public void setHtmlParams(List<HtmlParam> htmlParams) {
 304         this.htmlParams = htmlParams;
 305     }
 306 
 307     public void setOutfile(String outfile) {
 308         this.outfile = outfile;
 309     }
 310 
 311     public void setParams(List<Param> params) {
 312         this.params = params;
 313     }
 314 
 315     public void setPreloader(String preloader) {
 316         this.preloader = preloader;
 317     }
 318 
 319     public void setTitle(String title) {
 320         this.title = title;
 321     }
 322 
 323     public void setUpdateMode(String updateMode) {
 324         this.updateMode = updateMode;
 325     }
 326 
 327     public void setVendor(String vendor) {
 328         this.vendor = vendor;
 329     }
 330 
 331     public void setEmail(String email) {
 332         this.email = email;
 333     }
 334 
 335     public void setWidth(int width) {
 336         this.width = width;
 337     }
 338 
 339     public void setExtension(boolean isExtension) {
 340         this.isExtension = isExtension;
 341     }
 342 
 343     public void setApplicationClass(String applicationClass) {
 344         this.applicationClass = applicationClass;
 345     }
 346 
 347     public void setIncludeDT(boolean doEmbed) {
 348         includeDT = doEmbed;
 349     }
 350 
 351     public void setJSCallbacks(List<JSCallback> list) {
 352         callbacks = list;
 353     }
 354 
 355     public void setCallbacks(List<Callback> list) {
 356         List<JSCallback> jslist = new ArrayList<>(list.size());
 357         for (Callback cb: list) {
 358             jslist.add(new JSCallback(cb.getName(), cb.getCmd()));
 359         }
 360         callbacks = jslist;
 361     }
 362 
 363     static class Template {
 364         File in;
 365         File out;
 366 
 367         Template(File in, File out) {
 368             this.in = in;
 369             this.out = out;
 370         }
 371     }
 372 
 373     public void addTemplate(File in, File out) {
 374         templates.add(new Template(in, out));
 375     }
 376 
 377     //we need to expand as in some cases
 378     // (most notably javapackager)
 379     //we may get "." as filename and assumption is we include
 380     // everything in the given folder
 381     // (IOUtils.copyfiles() have recursive behavior)
 382     List<File> expandFileset(File root) {
 383         List<File> files = new LinkedList<>();
 384         if (com.oracle.tools.packager.IOUtils.isNotSymbolicLink(root)) {
 385             if (root.isDirectory()) {
 386                 File[] children = root.listFiles();
 387                 if (children != null) {
 388                     for (File f : children) {
 389                         files.addAll(expandFileset(f));
 390                     }
 391                 }
 392             } else {
 393                 files.add(root);
 394             }
 395         }
 396         return files;
 397     }
 398 
 399     @Override
 400     public void addResource(File baseDir, String path) {
 401         File file = new File(baseDir, path);
 402         //normalize top level dir
 403         // to strip things like "." in the path
 404         // or it can confuse symlink detection logic
 405         file = file.getAbsoluteFile();
 406 
 407         if (baseDir == null) {
 408             baseDir = file.getParentFile();
 409         }
 410         resources.add(new RelativeFileSet(baseDir, new LinkedHashSet<>(expandFileset(file))));
 411     }
 412 
 413     @Override
 414     public void addResource(File baseDir, File file) {
 415         //normalize initial file
 416         // to strip things like "." in the path
 417         // or it can confuse symlink detection logic
 418         file = file.getAbsoluteFile();
 419 
 420         if (baseDir == null) {
 421             baseDir = file.getParentFile();
 422         }
 423         resources.add(new RelativeFileSet(baseDir, new LinkedHashSet<>(expandFileset(file))));
 424     }
 425 
 426     public void addResource(File baseDir, String path, String type) {
 427         addResource(baseDir, createFile(baseDir, path), type);
 428     }
 429 
 430     public void addResource(File baseDir, File file, String type) {
 431         addResource(baseDir, file, "eager", type, null, null);
 432     }
 433 
 434     public void addResource(File baseDir, File file, String mode, String type, String os, String arch) {
 435         Set<File> singleFile = new LinkedHashSet<>();
 436         singleFile.add(file);
 437         if (baseDir == null) {
 438             baseDir = file.getParentFile();
 439         }
 440         RelativeFileSet rfs = new RelativeFileSet(baseDir, singleFile);
 441         rfs.setArch(arch);
 442         rfs.setMode(mode);
 443         rfs.setOs(os);
 444         rfs.setType(parseTypeFromString(type, file));
 445         resources.add(rfs);
 446     }
 447 
 448     private RelativeFileSet.Type parseTypeFromString(String type, File file) {
 449         if (type == null) {
 450             if (file.getName().endsWith(".jar")) {
 451                 return RelativeFileSet.Type.jar;
 452             } else if (file.getName().endsWith(".jnlp")) {
 453                 return RelativeFileSet.Type.jnlp;
 454             } else {
 455                 return RelativeFileSet.Type.UNKNOWN;
 456             }
 457         } else {
 458             return RelativeFileSet.Type.valueOf(type);
 459         }
 460     }
 461 
 462     private static File createFile(final File baseDir, final String path) {
 463         final File testFile = new File(path);
 464         return testFile.isAbsolute()
 465                 ? testFile
 466                 : new File(baseDir == null
 467                     ? null
 468                     : baseDir.getAbsolutePath(),
 469                       path);
 470     }
 471 
 472 
 473     @Override
 474     public void validate() throws PackagerException {
 475         if (outdir == null) {
 476             throw new PackagerException("ERR_MissingArgument", "-outdir");
 477         }
 478         if (outfile == null) {
 479             throw new PackagerException("ERR_MissingArgument", "-outfile");
 480         }
 481         if (resources.isEmpty()) {
 482             throw new PackagerException("ERR_MissingAppResources");
 483         }
 484         if (applicationClass == null) {
 485             throw new PackagerException("ERR_MissingArgument", "-appclass");
 486         }
 487     }
 488 
 489     //could be icon or splash
 490     static class Icon {
 491         final static int UNDEFINED = -1;
 492 
 493         String href;
 494         String kind;
 495         int width = UNDEFINED;
 496         int height = UNDEFINED;
 497         int depth = UNDEFINED;
 498         RunMode mode = RunMode.WEBSTART;
 499 
 500         Icon(String href, String kind, int w, int h, int d, RunMode m) {
 501             mode = m;
 502             this.href = href;
 503             this.kind = kind;
 504             if (w > 0) {
 505                 width = w;
 506             }
 507             if (h > 0) {
 508                 height = h;
 509             }
 510             if (d > 0) {
 511                 depth = d;
 512             }
 513         }
 514     }
 515 
 516     List<Icon> icons = new LinkedList<>();
 517 
 518     public void addIcon(String href, String kind, int w, int h, int d, RunMode m) {
 519         icons.add(new Icon(href, kind, w, h, d, m));
 520     }
 521 
 522     BundleType bundleType = BundleType.NONE;
 523     String targetFormat = null; //means any
 524 
 525     public void setBundleType(BundleType type) {
 526         bundleType = type;
 527     }
 528 
 529     public BundleType getBundleType() {
 530         return bundleType;
 531     }
 532 
 533     public void setTargetFormat(String t) {
 534         targetFormat = t;
 535     }
 536 
 537     public String getTargetFormat() {
 538         return targetFormat;
 539     }
 540 
 541     private String getArch() {
 542         String arch = System.getProperty("os.arch").toLowerCase();
 543 
 544         if ("x86".equals(arch) || "i386".equals(arch) || "i486".equals(arch)
 545                 || "i586".equals(arch) || "i686".equals(arch)) {
 546             arch = "x86";
 547         } else if ("x86_64".equals(arch) || "amd64".equals("arch")) {
 548             arch = "x86_64";
 549         }
 550 
 551         return arch;
 552     }
 553 
 554     static final Set<String> multi_args = new TreeSet<>(Arrays.asList(
 555             StandardBundlerParam.JVM_PROPERTIES.getID(),
 556             StandardBundlerParam.JVM_OPTIONS.getID(),
 557             StandardBundlerParam.USER_JVM_OPTIONS.getID(),
 558             StandardBundlerParam.ARGUMENTS.getID(),
 559             //StandardBundlerParam.MODULE_NAME.getID(),
 560             JLinkBundlerHelper.MODULE_PATH.getID(),
 561             JLinkBundlerHelper.JDK_MODULE_PATH.getID(),
 562             JLinkBundlerHelper.ADD_MODULES.getID(),
 563             JLinkBundlerHelper.LIMIT_MODULES.getID(),
 564             JLinkBundlerHelper.STRIP_NATIVE_COMMANDS.getID()
 565     ));
 566 
 567     @SuppressWarnings("unchecked")
 568     public void addBundleArgument(String key, Object value) {
 569         // special hack for multi-line arguments
 570         if (multi_args.contains(key) && value instanceof String) {
 571             Object existingValue = bundlerArguments.get(key);
 572             if (existingValue instanceof String) {
 573                 bundlerArguments.put(key, existingValue + "\n\n" + value);
 574             } else if (existingValue instanceof List) {
 575                 ((List)existingValue).add(value);
 576             } else if (existingValue instanceof Map && ((String)value).contains("=")) {
 577                 String[] mapValues = ((String)value).split("=", 2);
 578                 ((Map)existingValue).put(mapValues[0], mapValues[1]);
 579             } else {
 580                 bundlerArguments.put(key, value);
 581             }
 582         } else {
 583             bundlerArguments.put(key, value);
 584         }
 585     }
 586 
 587     public BundleParams getBundleParams() {
 588         BundleParams bundleParams = new BundleParams();
 589 
 590         //construct app resources
 591         //  relative to output folder!
 592         String currentOS = System.getProperty("os.name").toLowerCase();
 593         String currentArch = getArch();
 594 
 595         for (RelativeFileSet rfs : resources) {
 596             String os = rfs.getOs();
 597             String arch = rfs.getArch();
 598             //skip resources for other OS
 599             // and nativelib jars (we are including raw libraries)
 600             if ((os == null || currentOS.contains(os.toLowerCase())) &&
 601                     (arch == null || currentArch.startsWith(arch.toLowerCase()))
 602                     && rfs.getType() != RelativeFileSet.Type.nativelib) {
 603                 if (rfs.getType() == RelativeFileSet.Type.license) {
 604                     for (String s : rfs.getIncludedFiles()) {
 605                         bundleParams.addLicenseFile(s);
 606                     }
 607                 }
 608             }
 609         }
 610 
 611         bundleParams.setAppResourcesList(resources);
 612 
 613         bundleParams.setIdentifier(id);
 614 
 615         if (javaRuntimeWasSet) {
 616             bundleParams.setRuntime(javaRuntimeToUse);
 617         }
 618         bundleParams.setApplicationClass(applicationClass);
 619         bundleParams.setPrelaoderClass(preloader);
 620         bundleParams.setName(this.appName);
 621         bundleParams.setAppVersion(version);
 622         bundleParams.setType(bundleType);
 623         bundleParams.setBundleFormat(targetFormat);
 624         bundleParams.setVendor(vendor);
 625         bundleParams.setEmail(email);
 626         bundleParams.setShortcutHint(needShortcut);
 627         bundleParams.setMenuHint(needMenu);
 628         putUnlessNull(INSTALL_HINT.getID(), needInstall);
 629         bundleParams.setSystemWide(systemWide);
 630         bundleParams.setServiceHint(serviceHint);
 631         bundleParams.setInstalldirChooser(installdirChooser);
 632         bundleParams.setSignBundle(signBundle);
 633         bundleParams.setCopyright(copyright);
 634         bundleParams.setApplicationCategory(category);
 635         bundleParams.setLicenseType(licenseType);
 636         bundleParams.setDescription(description);
 637         bundleParams.setTitle(title);
 638         if (verbose) bundleParams.setVerbose(true);
 639 
 640         bundleParams.setJvmProperties(properties);
 641         bundleParams.setJvmargs(jvmargs);
 642         bundleParams.setJvmUserArgs(jvmUserArgs);
 643         bundleParams.setArguments(arguments);
 644 
 645         bundleParams.setAddModules(addModules);
 646         bundleParams.setLimitModules(limitModules);
 647         bundleParams.setDetectModules(detectModules);
 648         bundleParams.setStripExecutables(stripExecutables);
 649         bundleParams.setAppModulePath(jdkModulePath);
 650         bundleParams.setLinkModulePath(modulePath);
 651 
 652         File appIcon = null;
 653         List<Map<String, ? super Object>> bundlerIcons = new ArrayList<>();
 654         for (Icon ic: icons) {
 655             //NB: in theory we should be paying attention to RunMode but
 656             // currently everything is marked as webstart internally and runmode
 657             // is not publicly documented property
 658             if (/* (ic.mode == RunMode.ALL || ic.mode == RunMode.STANDALONE) && */
 659                 (ic.kind == null || ic.kind.equals("default")))
 660             {
 661                 //could be full path or something relative to the output folder
 662                 appIcon = new File(ic.href);
 663                 if (!appIcon.exists()) {
 664                     com.oracle.tools.packager.Log.debug("Icon [" + ic.href + "] is not valid absolute path. " +
 665                             "Assume it is relative to the output dir.");
 666                     appIcon = new File(outdir, ic.href);
 667                 }
 668             }
 669 
 670             Map<String, ? super Object> iconInfo = new TreeMap<>();
 671             if (ic.href != null) iconInfo.put(ICONS_HREF.getID(), ic.href);
 672             if (ic.kind != null) iconInfo.put(ICONS_KIND.getID(), ic.kind);
 673             if (ic.width > 0)    iconInfo.put(ICONS_WIDTH.getID(), Integer.toString(ic.width));
 674             if (ic.height > 0)   iconInfo.put(ICONS_HEIGHT.getID(), Integer.toString(ic.height));
 675             if (ic.depth > 0)    iconInfo.put(ICONS_DEPTH.getID(), Integer.toString(ic.depth));
 676 
 677             if (!iconInfo.isEmpty()) bundlerIcons.add(iconInfo);
 678         }
 679         putUnlessNullOrEmpty(ICONS.getID(), bundlerIcons);
 680 
 681         bundleParams.setIcon(appIcon);
 682 
 683         Map<String, String> paramsMap = new TreeMap<>();
 684         if (params != null) {
 685             for (Param p : params) {
 686                 paramsMap.put(p.name, p.value);
 687             }
 688         }
 689         putUnlessNullOrEmpty(JNLPBundler.APP_PARAMS.getID(), paramsMap);
 690 
 691         Map<String, String> unescapedHtmlParams = new TreeMap<>();
 692         Map<String, String> escapedHtmlParams = new TreeMap<>();
 693         if (htmlParams != null) {
 694             for (HtmlParam hp : htmlParams) {
 695                 if (hp.needEscape) {
 696                     escapedHtmlParams.put(hp.name, hp.value);
 697                 } else {
 698                     unescapedHtmlParams.put(hp.name, hp.value);
 699                 }
 700             }
 701         }
 702         putUnlessNullOrEmpty(JNLPBundler.APPLET_PARAMS.getID(), unescapedHtmlParams);
 703         putUnlessNullOrEmpty(ESCAPED_APPLET_PARAMS.getID(), escapedHtmlParams);
 704 
 705 
 706         putUnlessNull(WIDTH.getID(), width);
 707         putUnlessNull(HEIGHT.getID(), height);
 708         putUnlessNull(EMBEDDED_WIDTH.getID(), embeddedWidth);
 709         putUnlessNull(EMBEDDED_HEIGHT.getID(), embeddedHeight);
 710 
 711         putUnlessNull(CODEBASE.getID(), codebase);
 712         putUnlessNull(EMBED_JNLP.getID(), embedJNLP);
 713         // embedCertificates
 714         putUnlessNull(ALL_PERMISSIONS.getID(), allPermissions);
 715         putUnlessNull(UPDATE_MODE.getID(), updateMode);
 716         putUnlessNull(EXTENSION.getID(), isExtension);
 717         putUnlessNull(SWING_APP.getID(), isSwingApp);
 718 
 719         putUnlessNull(OUT_FILE.getID(), outfile);
 720         putUnlessNull(INCLUDE_DT.getID(), includeDT);
 721         putUnlessNull(PLACEHOLDER.getID(), placeholder);
 722         putUnlessNull(OFFLINE_ALLOWED.getID(), offlineAllowed);
 723 
 724         Map<String, String> callbacksMap = new TreeMap<>();
 725         if (callbacks != null) {
 726             for (JSCallback callback : callbacks) {
 727                 callbacksMap.put(callback.getName(), callback.getCmd());
 728             }
 729         }
 730         putUnlessNull(JS_CALLBACKS.getID(), callbacksMap);
 731 
 732         Map<File, File> templatesMap = new TreeMap<>();
 733         if (templates != null) {
 734             for (Template template : templates) {
 735                 templatesMap.put(template.in, template.out);
 736             }
 737         }
 738         putUnlessNull(TEMPLATES.getID(), templatesMap);
 739 
 740         putUnlessNull(FX_PLATFORM.getID(), fxPlatform);
 741         putUnlessNull(JRE_PLATFORM.getID(), jrePlatform);
 742 
 743         putUnlessNull(FALLBACK_APP.getID(), fallbackApp);
 744 
 745         // check for collisions
 746         TreeSet<String> keys = new TreeSet<>(bundlerArguments.keySet());
 747         keys.retainAll(bundleParams.getBundleParamsAsMap().keySet());
 748 
 749         if (!keys.isEmpty()) {
 750             throw new RuntimeException("Deploy Params and Bundler Arguments overlap in the following values:" + keys.toString());
 751         }
 752 
 753         bundleParams.addAllBundleParams(bundlerArguments);
 754 
 755         return bundleParams;
 756     }
 757 
 758     public void putUnlessNull(String param, Object value) {
 759         if (value != null) {
 760             bundlerArguments.put(param, value);
 761         }
 762     }
 763 
 764     public void putUnlessNullOrEmpty(String param, Map<?, ?> value) {
 765         if (value != null && !value.isEmpty()) {
 766             bundlerArguments.put(param, value);
 767         }
 768     }
 769 
 770     public void putUnlessNullOrEmpty(String param, Collection<?> value) {
 771         if (value != null && !value.isEmpty()) {
 772             bundlerArguments.put(param, value);
 773         }
 774     }
 775 }