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