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