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