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