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.ant;
  27 
  28 import java.io.File;
  29 import java.util.ArrayList;
  30 import java.util.LinkedList;
  31 import java.util.List;
  32 import java.util.Map;
  33 import java.util.stream.Collectors;
  34 
  35 import com.oracle.tools.packager.StandardBundlerParam;
  36 import com.sun.javafx.tools.ant.Platform.Jvmarg;
  37 import com.sun.javafx.tools.ant.Platform.Property;
  38 import com.sun.javafx.tools.packager.DeployParams;
  39 import com.oracle.tools.packager.Log;
  40 import com.sun.javafx.tools.packager.PackagerException;
  41 import com.sun.javafx.tools.packager.PackagerLib;
  42 import com.sun.javafx.tools.packager.bundlers.Bundler;
  43 import com.sun.javafx.tools.packager.bundlers.Bundler.Bundle;
  44 import com.sun.javafx.tools.packager.bundlers.Bundler.BundleType;
  45 import java.util.ResourceBundle;
  46 import org.apache.tools.ant.BuildException;
  47 import org.apache.tools.ant.DynamicAttribute;
  48 import org.apache.tools.ant.Task;
  49 import org.apache.tools.ant.types.DataType;
  50 
  51 /**
  52  * Generates package for Web deployment and redistribution of application.
  53  * Package includes of set of jar files, JNLP file and HTML file.
  54  *
  55  * Minimal example:
  56  * <pre>
  57  *   &lt;fx:deploy width="600" height="400"
  58  *                 outdir="web-dist" outfile="Fish"&gt;
  59  *       &lt;info title="Sample application"/&gt;
  60  *       &lt;fx:application refid="myapp"/&gt;
  61  *       &lt;fx:resources refid="myresources"/&gt;
  62  *   &lt;/fx:deploy&gt;
  63  * </pre>
  64  * Above example will generate HTML/JNLP files into the web-dist directory
  65  * and use "Fish" as prefix for generated files. Details about application and
  66  * its resources are defined elsewhere in the application and resource elements.
  67  * <p>
  68  * Minimal complete example:
  69  * <pre>
  70  *   &lt;fx:deploy width="600" height="400"
  71  *                 outdir="web-dist" outfile="Fish"&gt;
  72  *       &lt;info title="Sample application"/&gt;
  73  *       &lt;fx:application name="SampleApp"
  74  *              mainClass="testapp.MainApp"
  75  *              preloaderClass="testpreloader.Preloader"/&gt;
  76  *       &lt;fx:resources&gt;
  77  *              &lt;fx:fileset requiredFor="preloader" dir="dist"&gt;
  78  *                &lt;include name="preloader.jar"/&gt;
  79  *             &lt;/fx:fileset&gt;
  80  *              &lt;fx:fileset dir="dist"&gt;
  81  *                &lt;include name="helloworld.jar"/&gt;
  82  *             &lt;/fx:fileset&gt;
  83  *       &lt;/fx:resources&gt;
  84  *   &lt;/fx:deploy&gt;
  85  * </pre>
  86  * Same as above but here application and resource details are defined in place.
  87  * Note that using references helps with reducing code duplication as fx:jar need
  88  * to be used for double clickable jars.
  89  *
  90  * @ant.task name="deploy" category="javafx"
  91  */
  92 public class DeployFXTask extends Task implements DynamicAttribute {
  93 
  94     private static final ResourceBundle I18N =
  95             ResourceBundle.getBundle(DeployFXTask.class.getName());
  96 
  97     private String width = null;
  98     private String height = null;
  99     private String embeddedWidth = null;
 100     private String embeddedHeight = null;
 101     private String outfile = null;
 102     private String outdir = null;
 103     private boolean embedJNLP;
 104     private boolean isExtension = false;
 105     private Boolean signBundle;
 106 
 107     //Before FCS default is to include DT files with app
 108     // to ensure tests are using latest and compatible.
 109     //After FCS default is to use shared copy.
 110     private boolean includeDT = false;
 111 
 112     private String updateMode="background";
 113     private Info appInfo = null;
 114     private Application app = null;
 115     private Resources resources = null;
 116     private Preferences prefs = null;
 117     private String codebase = null;
 118 
 119     //container to embed application into
 120     //could be either string id or js code. If it is string id then it needs to
 121     //be escaped
 122     private String placeholder;
 123 
 124     private PackagerLib packager;
 125     private DeployParams deployParams;
 126 
 127     private Callbacks callbacks;
 128 
 129     boolean offlineAllowed = true;
 130 
 131     //default native bundle settings
 132     // use NONE to avoid large disk space and build time overhead
 133     BundleType nativeBundles = BundleType.NONE;
 134     String bundleFormat = null;
 135     boolean versionCheck = true;
 136 
 137     private boolean verbose = false;
 138     public void setVerbose(boolean v) {
 139         verbose = v;
 140     }
 141 
 142     public void setCodebase(String str) {
 143         codebase = str;
 144     }
 145 
 146     public DeployFXTask() {
 147         packager = new PackagerLib();
 148         deployParams = new DeployParams();
 149     }
 150 
 151     @Override
 152     public void execute() {
 153         boolean isModular = (app.getModule() != null) && !app.getModule().isEmpty();
 154         deployParams.setOutfile(outfile);
 155         deployParams.setOutdir(new File(outdir));
 156 
 157         if (versionCheck) {
 158             if (!com.sun.javafx.tools.ant.VersionCheck.isSameVersion()) {
 159                 throw new BuildException(I18N.getString("message.java.version.mismatch"));
 160             }
 161         }
 162 
 163         if (!isModular &&
 164             (nativeBundles == BundleType.JNLP ||
 165              nativeBundles == BundleType.ALL ||
 166              nativeBundles == BundleType.NONE)) {
 167             deployParams.setOfflineAllowed(offlineAllowed);
 168             deployParams.setVerbose(verbose);
 169             deployParams.setCodebase(codebase);
 170             deployParams.setSignBundle(signBundle);
 171 
 172             if (app.getModule() == null) {
 173                 deployParams.setApplicationClass(app.get().mainClass);
 174             }
 175 
 176             if (width != null) {
 177                 deployParams.setWidth(Integer.valueOf(width));
 178             }
 179 
 180             if (height != null) {
 181                 deployParams.setHeight(Integer.valueOf(height));
 182             }
 183 
 184             if (embeddedWidth != null && embeddedHeight != null) {
 185                 deployParams.setEmbeddedDimensions(embeddedWidth, embeddedHeight);
 186             }
 187 
 188             deployParams.setEmbedJNLP(embedJNLP);
 189             if (perms != null) {
 190                deployParams.setAllPermissions(perms.getElevated());
 191             }
 192 
 193             deployParams.setUpdateMode(updateMode);
 194             deployParams.setExtension(isExtension);
 195             deployParams.setIncludeDT(includeDT);
 196 
 197             if (callbacks != null) {
 198                 for (Callback cb: callbacks.callbacks) {
 199                     deployParams.addCallback(cb.getName(), cb.getCmd());
 200                 }
 201             }
 202 
 203             setPlatform();
 204             setPreferences();
 205 
 206             for (Template t: templateList) {
 207                 deployParams.addTemplate(t.infile, t.outfile);
 208             }
 209         }
 210 
 211         if (isModular &&
 212             (nativeBundles == BundleType.NATIVE ||
 213              nativeBundles == BundleType.IMAGE ||
 214              nativeBundles == BundleType.INSTALLER ||
 215              nativeBundles == BundleType.ALL)) {
 216             if (app != null) {
 217                 if (app.getModule() == null) {
 218                     deployParams.setApplicationClass(app.get().mainClass);
 219                 }
 220                 else {
 221                     int index = app.getModule().indexOf("/");
 222 
 223                     if (index > 0) {
 224                         deployParams.setModule(app.getModule());
 225                     }
 226                     else {
 227                         deployParams.setModule(app.getModule() + "/" + app.get().mainClass);
 228                     }
 229                 }
 230 
 231                 deployParams.setPreloader(app.get().preloaderClass);
 232                 deployParams.setAppId(app.get().id);
 233                 deployParams.setAppName(app.get().name);
 234                 deployParams.setParams(app.get().parameters);
 235                 deployParams.setArguments(app.get().getArguments());
 236                 deployParams.setHtmlParams(app.get().htmlParameters);
 237                 deployParams.setFallback(app.get().fallbackApp);
 238                 deployParams.setSwingAppWithEmbeddedJavaFX(app.get().embeddedIntoSwing);
 239                 deployParams.setVersion(app.get().version);
 240                 deployParams.setId(app.get().id);
 241                 deployParams.setServiceHint(app.get().daemon);
 242 
 243                 if (runtime != null) {
 244                     for (String s : runtime.getAddModules()) {
 245                         deployParams.addAddModule(s);
 246                     }
 247 
 248                     for (String s : runtime.getLimitModules()) {
 249                         deployParams.addLimitModule(s);
 250                     }
 251 
 252                     deployParams.setModulePath(runtime.getModulePath());
 253 
 254                     Boolean stripNativeCommands = runtime.getStripNativeCommands();
 255 
 256                     if (stripNativeCommands != null) {
 257                         deployParams.setStripNativeCommands(stripNativeCommands);
 258                     }
 259 
 260                     Boolean detectModules = runtime.getDetectModules();
 261 
 262                     if (detectModules != null) {
 263                         deployParams.setDetectModules(detectModules);
 264                     }
 265                 }
 266             }
 267 
 268             if (appInfo != null) {
 269                 deployParams.setTitle(appInfo.title);
 270                 deployParams.setVendor(appInfo.vendor);
 271                 deployParams.setDescription(appInfo.appDescription);
 272                 deployParams.setCategory(appInfo.category);
 273                 deployParams.setLicenseType(appInfo.licenseType);
 274                 deployParams.setCopyright(appInfo.copyright);
 275                 deployParams.setEmail(appInfo.email);
 276 
 277                 for (Info.Icon i: appInfo.icons) {
 278                     if (i instanceof Info.Splash) {
 279                        deployParams.addIcon(i.href, i.kind, i.width, i.height, i.depth,
 280                             ((Info.Splash) i).mode);
 281                     } else {
 282                        deployParams.addIcon(i.href, i.kind, i.width, i.height, i.depth,
 283                             DeployParams.RunMode.WEBSTART);
 284                     }
 285                 }
 286 
 287                 deployParams.addBundleArgument(StandardBundlerParam.FILE_ASSOCIATIONS.getID(),
 288                         appInfo.fileAssociations.stream()
 289                             .map(FileAssociation::createLauncherMap)
 290                             .collect(Collectors.toList()));
 291             }
 292 
 293             setPlatform();
 294             setPreferences();
 295         }
 296 
 297         if (!isModular &&
 298             (nativeBundles == BundleType.NATIVE ||
 299              nativeBundles == BundleType.IMAGE ||
 300              nativeBundles == BundleType.INSTALLER ||
 301              nativeBundles == BundleType.ALL)) {
 302             if (app != null) {
 303                 deployParams.setApplicationClass(app.get().mainClass);
 304                 deployParams.setPreloader(app.get().preloaderClass);
 305                 deployParams.setAppId(app.get().id);
 306                 deployParams.setAppName(app.get().name);
 307                 deployParams.setParams(app.get().parameters);
 308                 deployParams.setArguments(app.get().getArguments());
 309                 deployParams.setHtmlParams(app.get().htmlParameters);
 310                 deployParams.setFallback(app.get().fallbackApp);
 311                 deployParams.setSwingAppWithEmbeddedJavaFX(app.get().embeddedIntoSwing);
 312                 deployParams.setVersion(app.get().version);
 313                 deployParams.setId(app.get().id);
 314                 deployParams.setServiceHint(app.get().daemon);
 315             }
 316 
 317             if (appInfo != null) {
 318                 deployParams.setTitle(appInfo.title);
 319                 deployParams.setVendor(appInfo.vendor);
 320                 deployParams.setDescription(appInfo.appDescription);
 321                 deployParams.setCategory(appInfo.category);
 322                 deployParams.setLicenseType(appInfo.licenseType);
 323                 deployParams.setCopyright(appInfo.copyright);
 324                 deployParams.setEmail(appInfo.email);
 325 
 326                 for (Info.Icon i: appInfo.icons) {
 327                     if (i instanceof Info.Splash) {
 328                        deployParams.addIcon(i.href, i.kind, i.width, i.height, i.depth,
 329                             ((Info.Splash) i).mode);
 330                     } else {
 331                        deployParams.addIcon(i.href, i.kind, i.width, i.height, i.depth,
 332                             DeployParams.RunMode.WEBSTART);
 333                     }
 334                 }
 335 
 336                 deployParams.addBundleArgument(StandardBundlerParam.FILE_ASSOCIATIONS.getID(),
 337                         appInfo.fileAssociations.stream()
 338                             .map(FileAssociation::createLauncherMap)
 339                             .collect(Collectors.toList()));
 340             }
 341 
 342             setPlatform();
 343             setPreferences();
 344         }
 345 
 346         for (BundleArgument ba : bundleArgumentList) {
 347             deployParams.addBundleArgument(ba.arg, ba.value);
 348         }
 349 
 350         deployParams.setPlaceholder(placeholder);
 351 
 352         if (resources != null) {
 353             for (FileSet fs: resources.getResources()) {
 354                 Utils.addResources(deployParams, fs);
 355             }
 356         }
 357 
 358         List<Map<String, ? super Object>> launchersAsMap = new ArrayList<>();
 359         for (SecondaryLauncher sl : secondaryLaunchers) {
 360             launchersAsMap.add(sl.createLauncherMap());
 361         }
 362 
 363         deployParams.addBundleArgument(
 364                 StandardBundlerParam.SECONDARY_LAUNCHERS.getID(),
 365                 launchersAsMap);
 366 
 367         deployParams.setBundleType(nativeBundles);
 368         deployParams.setTargetFormat(bundleFormat);
 369 
 370         Log.setLogger(new AntLog(this.getProject()));
 371 
 372         try {
 373             packager.generateDeploymentPackages(deployParams);
 374         } catch (PackagerException pe) {
 375             if (pe.getCause() != null) {
 376                throw new BuildException(pe.getCause().getMessage(), pe.getCause());
 377             } else {
 378                 throw new BuildException(pe.getMessage(), pe);
 379             }
 380         } catch (Exception e) {
 381             throw new BuildException(e.getMessage(), e);
 382         } finally {
 383             Log.setLogger(null);
 384         }
 385     }
 386 
 387     /**
 388      * Set to true if we are generating an 'extension' JNLP.
 389      *
 390      * @ant.not-required Default is false.
 391      */
 392     public void setExtension(boolean v) {
 393         isExtension = v;
 394     }
 395 
 396     public void setNativeBundles(String v) {
 397         Bundle bundle = Bundler.stringToBundle(v);
 398         this.nativeBundles = bundle.type;
 399         this.bundleFormat = bundle.format;
 400     }
 401 
 402     public void setVersionCheck(String value) {
 403         this.versionCheck = Boolean.valueOf(value);
 404     }
 405 
 406     /**
 407      * Indicates the preferences for when checks for application updates
 408      * are performed. Supported modes are always, timeout and background.
 409      *
 410      * @ant.not-required Default is background.
 411      */
 412     public void setUpdateMode(String v) {
 413         String l = v.toLowerCase();
 414         if ("eager".equals(l)) {
 415             //workaround for doc bug in 2.0
 416             l="always";
 417         }
 418         if (!"always".equals(l) && !"background".equals(l)
 419                 && !"timeout".equals(l)) {
 420             throw new BuildException("Unknown update mode: ["+l+"]." +
 421                     "Supported modes are: 'always', 'timeout' and 'background'");
 422         }
 423         updateMode = l;
 424     }
 425 
 426     /**
 427      * Indicates if the application can be launched offline.
 428      *
 429      * If application is already downloaded and update mode is eager then
 430      * the check will timeout after a few seconds, in which case the cached
 431      * application will be launched instead.
 432      *
 433      * Given a reasonably fast server connection,
 434      * the latest version of the application will usually be run,
 435      * but it is not guaranteed. The application, however, can be run offline.
 436      *
 437      * @ant.not-required Default is true.
 438      */
 439     public void setOfflineAllowed(boolean v) {
 440         offlineAllowed = v;
 441     }
 442 
 443     /**
 444      * Application width for embedding application into Web page
 445      *
 446      * @ant.optional
 447      */
 448     public void setEmbeddedWidth(String w) {
 449         embeddedWidth = w;
 450     }
 451 
 452     /**
 453      * Application width. Used for webstart and embedded applications
 454      * unless emdeddedWidth is specified
 455      *
 456      * @ant.required
 457      */
 458     public void setWidth(String v) {
 459         width = v;
 460     }
 461 
 462     /**
 463      * Application width for embedding application into Web page
 464      *
 465      * @ant.optional
 466      */
 467     public void setEmbeddedHeight(String w) {
 468         embeddedHeight = w;
 469     }
 470 
 471     /**
 472      * Application height. Used for webstart and embedded applications
 473      * unless emdeddedHeight is specified
 474      *
 475      * @ant.required
 476      */
 477     public void setHeight(String v) {
 478         height = v;
 479     }
 480 
 481     /**
 482      * Enable embedding JNLP descriptor into Web page.
 483      * Reduces number of network connections to be made on startup and
 484      * help to improve startup time.
 485      *
 486      * @ant.not-required Default is false.
 487      */
 488     public void setEmbedJNLP(boolean v) {
 489         embedJNLP = v;
 490     }
 491 
 492     /**
 493      * Directory where application package will be saved.
 494      *
 495      * @ant.required
 496      */
 497     public void setOutdir(String v) {
 498         outdir = v;
 499     }
 500 
 501     /**
 502      * Prefix to be used for new generated files.
 503      *
 504      * @ant.required
 505      */
 506     public void setOutfile(String v) {
 507         outfile = v;
 508     }
 509 
 510     /**
 511      * If true then web deployment is done using javascript files
 512      * on java.com. Otherwise copy of javascript file is included into
 513      * application package.
 514      *
 515      * @ant.not-required Before FCS default is false. For FCS default is true.
 516      */
 517     public void setIncludeDT(Boolean v) {
 518         includeDT = v;
 519     }
 520 
 521     /**
 522      * Placeholder in the web page where application will be embedded.
 523      * This is expected to be Javascript DOM object.
 524      *
 525      * @ant.required Either reference or id of placeholder is required.
 526      */
 527     public void setPlaceholderRef(String p) {
 528         this.placeholder = p;
 529     }
 530 
 531     /**
 532      * Id of the placeholder in the web page where application will be embedded.
 533      * Javascript's document.getElementById() is expected to be able to resolve it.
 534      *
 535      * @ant.required Either reference or id of placeholder is required.
 536      */
 537     public void setPlaceholderId(String id) {
 538         //raw id of the placeholder, need to escape it
 539         this.placeholder = "'"+id+"'";
 540     }
 541 
 542     public void setSignBundle(boolean signBundle) {
 543         this.signBundle = signBundle;
 544     }
 545 
 546     public Info createInfo() {
 547         appInfo = new Info();
 548         return appInfo;
 549     }
 550 
 551     public Application createApplication() {
 552         app = new Application();
 553         return app;
 554     }
 555 
 556     public Preferences createPreferences() {
 557         prefs = new Preferences();
 558         return prefs;
 559     }
 560 
 561     public Callbacks createCallbacks() {
 562         if (callbacks != null) {
 563             throw new BuildException("Only one callbacks element is supported.");
 564         }
 565         callbacks = new Callbacks();
 566         return callbacks;
 567     }
 568 
 569     public Resources createResources() {
 570         if (resources != null) {
 571             throw new BuildException("Only one resources element is supported.");
 572         }
 573         resources = new Resources();
 574         return resources;
 575     }
 576 
 577     List<Template> templateList = new LinkedList<>();
 578 
 579     public Template createTemplate() {
 580         Template t = new Template();
 581         templateList.add(t);
 582         return t;
 583     }
 584 
 585     Platform platform;
 586 
 587     public Platform createPlatform() {
 588         platform = new Platform();
 589         return platform;
 590     }
 591 
 592     private Permissions perms = null;
 593 
 594     public Permissions createPermissions() {
 595         perms = new Permissions();
 596         return perms;
 597     }
 598 
 599     List<BundleArgument> bundleArgumentList = new LinkedList<>();
 600 
 601     public BundleArgument createBundleArgument() {
 602         BundleArgument ba = new BundleArgument();
 603         bundleArgumentList.add(ba);
 604         return ba;
 605     }
 606 
 607     private List<SecondaryLauncher> secondaryLaunchers = new ArrayList<>();
 608 
 609     public SecondaryLauncher createSecondaryLauncher() {
 610         SecondaryLauncher sl = new SecondaryLauncher();
 611         secondaryLaunchers.add(sl);
 612         return sl;
 613     }
 614 
 615     private Runtime runtime = null;
 616 
 617     public Runtime createRuntime() {
 618         runtime = new Runtime();
 619         return runtime;
 620     }
 621 
 622     @Override
 623     public void setDynamicAttribute(String name, String value) throws BuildException {
 624         //Use qName and value - can't really validate anything until we know which bundlers we have, so this has
 625         //to done (way) downstream
 626         bundleArgumentList.add(new BundleArgument(name, value));
 627     }
 628 
 629     private void setPlatform() {
 630         if (platform != null) {
 631             Platform pl = platform.get();
 632             if (pl.j2se != null) {
 633                 deployParams.setJRE(pl.j2se);
 634             }
 635             if (pl.javafx != null) {
 636                 deployParams.setJavafx(pl.javafx);
 637             }
 638 
 639             //only pass it further if it was explicitly set
 640             // as we do not want to override default
 641             if (pl.javaRoot != null) {
 642                 if (Platform.USE_SYSTEM_JRE.equals(pl.javaRoot)) {
 643                     deployParams.setJavaRuntimeSource(null);
 644                 } else {
 645                     deployParams.setJavaRuntimeSource(new File(pl.javaRoot));
 646                 }
 647             }
 648 
 649             for (Property p: pl.properties) {
 650                 deployParams.addJvmProperty(p.name, p.value);
 651             }
 652             for (Jvmarg a: pl.jvmargs) {
 653                 deployParams.addJvmArg(a.value);
 654             }
 655             for (Property a: pl.jvmUserArgs) {
 656                 deployParams.addJvmUserArg(a.name, a.value);
 657             }
 658         }
 659     }
 660 
 661     private void setPreferences() {
 662         if (prefs != null) {
 663             deployParams.setNeedShortcut(prefs.getShortcut());
 664             deployParams.setNeedInstall(prefs.getInstall());
 665             deployParams.setNeedMenu(prefs.getMenu());
 666             deployParams.setSystemWide(prefs.getSystemInstall());
 667             deployParams.setInstalldirChooser(prefs.getInstalldirChooser());
 668         }
 669     }
 670 
 671     /**
 672      * Template to preprocess.
 673      * <p>
 674      * Template is the HTML file containing markers to be replaced with
 675      * javascript or HTML snippets needed to deploy JavaFX application on the
 676      * Web page. This allows to deploy application into "real" Web pages
 677      * and simplify development process if application is tightly
 678      * integrated with the page (e.g. uses javascript to communicate to it).
 679      * <p>
 680      * Marker has the form of #XXX# or #XXX(id)#. Where id is identifier
 681      * of an application and XXX is one of following:
 682      * <ul>
 683      *   <li>DT.SCRIPT.URL - location of dtjava.js
 684      *   <li>DT.SCRIPT.CODE - script element to include dtjava.js
 685      *   <li>DT.EMBED.CODE.DYNAMIC - code to embed application into given placeholder
 686      *         It is expected it will be wrapped into function()
 687      *   <li>DT.EMBED.CODE.ONLOAD - all code needed to embed application into Web page
 688      *               using onload hook (except inclusion of dtjava.js)
 689      *   <li>DT.LAUNCH.CODE - code need to launch application.
 690      *          Expected to be wrappend into function().
 691      * </ul>
 692      *
 693      * Page with multiple different applications can be processed multiple times
 694      * - one per application. To avoid confusion markers need to use
 695      * application ids  (alphanumeric string no spaces).
 696      * <p>
 697      * If input and output files are the same then template is processed in place.
 698      * <p>
 699      * Example:
 700      * <pre>
 701      *     &lt;template file="App_template.html" tofile="App.html"/&gt;
 702      * </pre>
 703      *
 704      * @ant.type name="Template" category="javafx"
 705      */
 706     public static class Template extends DataType {
 707         File infile = null;
 708         File outfile = null;
 709 
 710         /**
 711          * Input file.
 712          *
 713          * @ant.required
 714          */
 715         public void setFile(File f) {
 716             infile = f;
 717         }
 718 
 719         /**
 720          * Output file (after preprocessing).
 721          *
 722          * @ant.not-required Default is the same as input file.
 723          */
 724         public void setTofile(File f) {
 725             outfile = f;
 726         }
 727     }
 728 
 729     /**
 730      * An argument to be passed off to the bundlers.
 731      *
 732      * Each bundler uses a set of arguments that may be shared across
 733      * the different bundlers or it may be specific to each bundler.
 734      *
 735      * Some bundlers declare argument types that are not known to the JDK
 736      * and may be specific to the particular bundler (such as Mac App Store
 737      * categories).  These arguments allow you to set and adjust these a
 738      * rguments.
 739      *
 740      * @ant.type name="BundleArgument" category="javafx"
 741      */
 742     public static class BundleArgument extends DataType {
 743         String arg = null;
 744         String value = null;
 745 
 746         BundleArgument() {
 747 
 748         }
 749 
 750         BundleArgument(String arg, String value) {
 751             this.arg = arg;
 752             this.value = value;
 753         }
 754 
 755         /**
 756          * Name of the bundle argument.
 757          *
 758          * @ant.required
 759          */
 760         public void setArg(String arg) {
 761             this.arg = arg;
 762         }
 763 
 764         /**
 765          * Value for the bundle argument.
 766          *
 767          * @ant.not-required Default is a literal null
 768          */
 769         public void setValue(String value) {
 770             this.value = value;
 771         }
 772     }
 773 }