src/demo/share/jpackager/JNLPConverter/src/jnlp/converter/parser/XMLFormat.java
branchJDK-8200758-branch
changeset 56963 eaca4369b068
equal deleted inserted replaced
56962:a769ad2d40d6 56963:eaca4369b068
       
     1 /*
       
     2  * Copyright (c) 2006, 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.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package jnlp.converter.parser;
       
    25 
       
    26 import java.net.URL;
       
    27 import java.util.Arrays;
       
    28 import java.util.ArrayList;
       
    29 import jnlp.converter.JNLPConverter;
       
    30 import jnlp.converter.parser.exception.MissingFieldException;
       
    31 import jnlp.converter.parser.exception.BadFieldException;
       
    32 import jnlp.converter.parser.exception.JNLParseException;
       
    33 import jnlp.converter.parser.xml.XMLEncoding;
       
    34 import jnlp.converter.parser.xml.XMLParser;
       
    35 import jnlp.converter.parser.xml.XMLNode;
       
    36 import jnlp.converter.parser.JNLPDesc.AssociationDesc;
       
    37 import jnlp.converter.parser.JNLPDesc.IconDesc;
       
    38 import jnlp.converter.parser.JNLPDesc.InformationDesc;
       
    39 import jnlp.converter.parser.JNLPDesc.ShortcutDesc;
       
    40 import jnlp.converter.parser.ResourcesDesc.JARDesc;
       
    41 import jnlp.converter.parser.ResourcesDesc.JREDesc;
       
    42 import jnlp.converter.Log;
       
    43 import jnlp.converter.parser.ResourcesDesc.ExtensionDesc;
       
    44 import jnlp.converter.parser.ResourcesDesc.PropertyDesc;
       
    45 import org.xml.sax.SAXParseException;
       
    46 
       
    47 public class XMLFormat {
       
    48 
       
    49     public static XMLNode parseBits(byte[] bits) throws JNLParseException {
       
    50         return parse(decode(bits));
       
    51     }
       
    52 
       
    53     private static String decode(byte[] bits) throws JNLParseException {
       
    54         try {
       
    55             return XMLEncoding.decodeXML(bits);
       
    56         } catch (Exception e) {
       
    57             throw new JNLParseException(e,
       
    58                 "exception determining encoding of jnlp file", 0);
       
    59         }
       
    60     }
       
    61 
       
    62     private static XMLNode parse(String source) throws JNLParseException {
       
    63         try {
       
    64             return (new XMLParser(source).parse());
       
    65         } catch (SAXParseException spe) {
       
    66             throw new JNLParseException(spe,
       
    67                         "exception parsing jnlp file", spe.getLineNumber());
       
    68         } catch (Exception e) {
       
    69             throw new JNLParseException(e,
       
    70                         "exception parsing jnlp file", 0);
       
    71         }
       
    72     }
       
    73 
       
    74     /**
       
    75      * thisCodebase, if set, is used to determine the codebase,
       
    76      *     if JNLP codebase is not absolute.
       
    77      *
       
    78      * @param thisCodebase base URL of this JNLPDesc location
       
    79      */
       
    80     public static JNLPDesc parse(byte[] bits, URL thisCodebase, String jnlp)
       
    81             throws Exception {
       
    82 
       
    83         JNLPDesc jnlpd = new JNLPDesc();
       
    84         String source = decode(bits).trim();
       
    85         XMLNode root = parse(source);
       
    86 
       
    87         if (root == null || root.getName() == null) {
       
    88             throw new JNLParseException(null, null, 0);
       
    89         }
       
    90 
       
    91         // Check that root element is a <jnlp> tag
       
    92         if (!root.getName().equals("jnlp")) {
       
    93             throw (new MissingFieldException(source, "<jnlp>"));
       
    94         }
       
    95 
       
    96         // Read <jnlp> attributes (path is empty, i.e., "")
       
    97         // (spec, version, codebase, href)
       
    98         String specVersion = XMLUtils.getAttribute(root, "", "spec", "1.0+");
       
    99         jnlpd.setSpecVersion(specVersion);
       
   100         String version = XMLUtils.getAttribute(root, "", "version");
       
   101         jnlpd.setVersion(version);
       
   102 
       
   103         // Make sure the codebase URL ends with a '/'.
       
   104         //
       
   105         // Regarding the JNLP spec,
       
   106         // the thisCodebase is used to determine the codebase.
       
   107         //      codebase = new URL(thisCodebase, codebase)
       
   108         URL codebase = GeneralUtil.asPathURL(XMLUtils.getAttributeURL(source,
       
   109             thisCodebase, root, "", "codebase"));
       
   110         if (codebase == null && thisCodebase != null) {
       
   111             codebase = thisCodebase;
       
   112         }
       
   113         jnlpd.setCodebase(codebase.toExternalForm());
       
   114 
       
   115         // Get href for JNLP file
       
   116         URL href = XMLUtils.getAttributeURL(source, codebase, root, "", "href");
       
   117         jnlpd.setHref(href.toExternalForm());
       
   118 
       
   119         // Read <security> attributes
       
   120         if (XMLUtils.isElementPath(root, "<security><all-permissions>")) {
       
   121             jnlpd.setIsSandbox(false);
       
   122         } else if (XMLUtils.isElementPath(root,
       
   123                 "<security><j2ee-application-client-permissions>")) {
       
   124             jnlpd.setIsSandbox(false);
       
   125         }
       
   126 
       
   127         // We can be fxapp, and also be applet, or application, or neither
       
   128         boolean isFXApp = false;
       
   129         boolean isApplet = false;
       
   130         if (XMLUtils.isElementPath(root, "<javafx-desc>")) {
       
   131             // no new type for javafx-desc - needs one of the others
       
   132             buildFXAppDesc(source, root, "<javafx-desc>", jnlpd);
       
   133             jnlpd.setIsFXApp(true);
       
   134             isFXApp = true;
       
   135         }
       
   136 
       
   137         /*
       
   138          * Note - the jnlp specification says there must be exactly one of
       
   139          * the descriptor types.  This code has always violated (or at least
       
   140          * not checked for) that condition.
       
   141          * Instead it uses precedent order app, component, installer, applet
       
   142          * and ignores any other descriptors given.
       
   143          */
       
   144         if (XMLUtils.isElementPath(root, "<application-desc>")) {
       
   145             buildApplicationDesc(source, root, jnlpd);
       
   146         } else if (XMLUtils.isElementPath(root, "<component-desc>")) {
       
   147             jnlpd.setIsLibrary(true);
       
   148         } else if (XMLUtils.isElementPath(root, "<installer-desc>")) {
       
   149             Log.warning("<installer-desc> is not supported and will be ignored in " + jnlp);
       
   150             jnlpd.setIsInstaller(true);
       
   151         } else if (XMLUtils.isElementPath(root, "<applet-desc>")) {
       
   152             isApplet = true;
       
   153         } else {
       
   154             if (!isFXApp) {
       
   155                 throw (new MissingFieldException(source,
       
   156                     "<jnlp>(<application-desc>|<applet-desc>|" +
       
   157                     "<installer-desc>|<component-desc>)"));
       
   158             }
       
   159         }
       
   160 
       
   161         if (isApplet && !isFXApp) {
       
   162             Log.error("Applet based applications deployed with <applet-desc> element are not supported.");
       
   163         }
       
   164 
       
   165         if (!jnlpd.isLibrary() && !jnlpd.isInstaller()) {
       
   166             buildInformationDesc(source, codebase, root, jnlpd);
       
   167         }
       
   168 
       
   169         if (!jnlpd.isInstaller()) {
       
   170             buildResourcesDesc(source, codebase, root, false, jnlpd);
       
   171         }
       
   172 
       
   173         if (!jnlpd.isLibrary() && !jnlpd.isInstaller()) {
       
   174             jnlpd.parseResourceDesc();
       
   175         }
       
   176 
       
   177         if (!jnlpd.isInstaller()) {
       
   178             if (jnlpd.isSandbox()) {
       
   179                 if (jnlpd.isLibrary()) {
       
   180                     Log.warning(jnlp + " is sandbox extension. JNLPConverter does not support sandbox environment and converted application will run without security manager.");
       
   181                 } else {
       
   182                     Log.warning("This is sandbox Web-Start application. JNLPConverter does not support sandbox environment and converted application will run without security manager.");
       
   183                 }
       
   184             }
       
   185         }
       
   186 
       
   187         return jnlpd;
       
   188     }
       
   189 
       
   190     /**
       
   191      * Create a combine informationDesc in the two informationDesc.
       
   192      * The information present in id1 overwrite the information present in id2
       
   193      */
       
   194     private static InformationDesc combineInformationDesc(
       
   195                                    InformationDesc id1, InformationDesc id2) {
       
   196         if (id1 == null) {
       
   197             return id2;
       
   198         }
       
   199         if (id2 == null) {
       
   200             return id1;
       
   201         }
       
   202 
       
   203         String t1 = id1.getTitle();
       
   204         String title  = (t1 != null && t1.length() > 0) ?
       
   205             t1 : id2.getTitle();
       
   206         String v1 = id1.getVendor();
       
   207         String vendor = (v1 != null && v1.length() > 0) ?
       
   208             v1 : id2.getVendor();
       
   209 
       
   210         /** Copy descriptions */
       
   211         String[] descriptions = new String[InformationDesc.NOF_DESC];
       
   212         for (int i = 0; i < descriptions.length; i++) {
       
   213             descriptions[i] = (id1.getDescription(i) != null)
       
   214                     ? id1.getDescription(i) : id2.getDescription(i);
       
   215         }
       
   216 
       
   217         /** Icons */
       
   218         ArrayList<IconDesc> iconList = new ArrayList<>();
       
   219         if (id2.getIcons() != null) {
       
   220             iconList.addAll(Arrays.asList(id2.getIcons()));
       
   221         }
       
   222         if (id1.getIcons() != null) {
       
   223             iconList.addAll(Arrays.asList(id1.getIcons()));
       
   224         }
       
   225         IconDesc[] icons = new IconDesc[iconList.size()];
       
   226         icons = iconList.toArray(icons);
       
   227 
       
   228         ShortcutDesc hints = (id1.getShortcut() != null) ?
       
   229                              id1.getShortcut() : id2.getShortcut();
       
   230 
       
   231         AssociationDesc[] asd = ( AssociationDesc[] ) addArrays(
       
   232             (Object[])id1.getAssociations(), (Object[])id2.getAssociations());
       
   233 
       
   234         return new InformationDesc(title,
       
   235                                    vendor,
       
   236                                    descriptions,
       
   237                                    icons,
       
   238                                    hints,
       
   239                                    asd);
       
   240     }
       
   241 
       
   242     /** Extract data from <information> tag */
       
   243     private static void buildInformationDesc(final String source, final URL codebase, XMLNode root, JNLPDesc jnlpd)
       
   244         throws MissingFieldException, BadFieldException {
       
   245         final ArrayList<InformationDesc> list = new ArrayList<>();
       
   246 
       
   247         // Iterates over all <information> nodes ignoring the type
       
   248         XMLUtils.visitElements(root,
       
   249             "<information>", new XMLUtils.ElementVisitor() {
       
   250             @Override
       
   251             public void visitElement(XMLNode e) throws
       
   252                 BadFieldException, MissingFieldException {
       
   253 
       
   254                 // Check for right os, arch, and locale
       
   255                 String[] os = GeneralUtil.getStringList(
       
   256                             XMLUtils.getAttribute(e, "", "os", null));
       
   257                 String[] arch = GeneralUtil.getStringList(
       
   258                             XMLUtils.getAttribute(e, "", "arch", null));
       
   259                 String[] locale = GeneralUtil.getStringList(
       
   260                             XMLUtils.getAttribute(e, "", "locale", null));
       
   261                 if (GeneralUtil.prefixMatchStringList(
       
   262                                 os, GeneralUtil.getOSFullName()) &&
       
   263                     GeneralUtil.prefixMatchArch(arch) &&
       
   264                     matchDefaultLocale(locale))
       
   265                 {
       
   266                     // Title, vendor
       
   267                     String title = XMLUtils.getElementContents(e, "<title>");
       
   268                     String vendor = XMLUtils.getElementContents(e, "<vendor>");
       
   269 
       
   270                     // Descriptions
       
   271                     String[] descriptions =
       
   272                                 new String[InformationDesc.NOF_DESC];
       
   273                     descriptions[InformationDesc.DESC_DEFAULT] =
       
   274                         XMLUtils.getElementContentsWithAttribute(
       
   275                         e, "<description>", "kind", "", null);
       
   276                     descriptions[InformationDesc.DESC_ONELINE] =
       
   277                         XMLUtils.getElementContentsWithAttribute(
       
   278                         e, "<description>", "kind", "one-line", null);
       
   279                     descriptions[InformationDesc.DESC_SHORT] =
       
   280                         XMLUtils.getElementContentsWithAttribute(
       
   281                         e, "<description>", "kind", "short", null);
       
   282                     descriptions[InformationDesc.DESC_TOOLTIP] =
       
   283                         XMLUtils.getElementContentsWithAttribute(
       
   284                         e, "<description>", "kind", "tooltip", null);
       
   285 
       
   286                     // Icons
       
   287                     IconDesc[] icons = getIconDescs(source, codebase, e);
       
   288 
       
   289                     // Shortcut hints
       
   290                     ShortcutDesc shortcuts = getShortcutDesc(e);
       
   291 
       
   292                     // Association hints
       
   293                     AssociationDesc[] associations = getAssociationDesc(
       
   294                                                         source, codebase, e);
       
   295 
       
   296                     list.add(new InformationDesc(
       
   297                         title, vendor, descriptions, icons,
       
   298                         shortcuts, associations));
       
   299                 }
       
   300             }
       
   301         });
       
   302 
       
   303         /* Combine all information desc. information in a single one for
       
   304          * the current locale using the following priorities:
       
   305          *   1. locale == language_country_variant
       
   306          *   2. locale == lauguage_country
       
   307          *   3. locale == lauguage
       
   308          *   4. no or empty locale
       
   309          */
       
   310         InformationDesc normId = new InformationDesc(null, null, null, null, null, null);
       
   311         for (InformationDesc id : list) {
       
   312             normId = combineInformationDesc(id, normId);
       
   313         }
       
   314 
       
   315         jnlpd.setTitle(normId.getTitle());
       
   316         jnlpd.setVendor(normId.getVendor());
       
   317         jnlpd.setDescriptions(normId.getDescription());
       
   318         jnlpd.setIcons(normId.getIcons());
       
   319         jnlpd.setShortcuts(normId.getShortcut());
       
   320         jnlpd.setAssociations(normId.getAssociations());
       
   321     }
       
   322 
       
   323     private static Object[] addArrays (Object[] a1, Object[] a2) {
       
   324         if (a1 == null) {
       
   325             return a2;
       
   326         }
       
   327         if (a2 == null) {
       
   328             return a1;
       
   329         }
       
   330         ArrayList<Object> list = new ArrayList<>();
       
   331         int i;
       
   332         for (i=0; i<a1.length; list.add(a1[i++]));
       
   333         for (i=0; i<a2.length; list.add(a2[i++]));
       
   334         return list.toArray(a1);
       
   335     }
       
   336 
       
   337     public static boolean matchDefaultLocale(String[] localeStr) {
       
   338         return GeneralUtil.matchLocale(localeStr, GeneralUtil.getDefaultLocale());
       
   339     }
       
   340 
       
   341     /** Extract data from <resources> tag. There is only one. */
       
   342     static void buildResourcesDesc(final String source,
       
   343             final URL codebase, XMLNode root, final boolean ignoreJres, JNLPDesc jnlpd)
       
   344             throws MissingFieldException, BadFieldException {
       
   345         // Extract classpath directives
       
   346         final ResourcesDesc rdesc = new ResourcesDesc();
       
   347 
       
   348         // Iterate over all entries
       
   349         XMLUtils.visitElements(root, "<resources>",
       
   350                 new XMLUtils.ElementVisitor() {
       
   351             @Override
       
   352             public void visitElement(XMLNode e)
       
   353                     throws MissingFieldException, BadFieldException {
       
   354                 // Check for right os, archictecture, and locale
       
   355                 String[] os = GeneralUtil.getStringList(
       
   356                         XMLUtils.getAttribute(e, "", "os", null));
       
   357                 final String arch = XMLUtils.getAttribute(e, "", "arch", null);
       
   358                 String[] locale = GeneralUtil.getStringList(
       
   359                         XMLUtils.getAttribute(e, "", "locale", null));
       
   360                 if (GeneralUtil.prefixMatchStringList(
       
   361                         os, GeneralUtil.getOSFullName())
       
   362                         && matchDefaultLocale(locale)) {
       
   363                     // Now visit all children in this node
       
   364                     XMLUtils.visitChildrenElements(e,
       
   365                             new XMLUtils.ElementVisitor() {
       
   366                         @Override
       
   367                         public void visitElement(XMLNode e2)
       
   368                                 throws MissingFieldException, BadFieldException {
       
   369                             handleResourceElement(source, codebase,
       
   370                                     e2, rdesc, ignoreJres, arch, jnlpd);
       
   371                         }
       
   372                     });
       
   373                 }
       
   374             }
       
   375         });
       
   376 
       
   377         if (!rdesc.isEmpty()) {
       
   378             jnlpd.setResourcesDesc(rdesc);
       
   379         }
       
   380     }
       
   381 
       
   382     private static IconDesc[] getIconDescs(final String source,
       
   383             final URL codebase, XMLNode e)
       
   384             throws MissingFieldException, BadFieldException {
       
   385         final ArrayList<IconDesc> answer = new ArrayList<>();
       
   386         XMLUtils.visitElements(e, "<icon>", new XMLUtils.ElementVisitor() {
       
   387             @Override
       
   388             public void visitElement(XMLNode icon) throws
       
   389                     MissingFieldException, BadFieldException {
       
   390                 String kindStr = XMLUtils.getAttribute(icon, "", "kind", "");
       
   391                 URL href = XMLUtils.getRequiredURL(source, codebase, icon, "", "href");
       
   392 
       
   393                 if (href != null) {
       
   394                     if (!JNLPConverter.isIconSupported(href.toExternalForm())) {
       
   395                         return;
       
   396                     }
       
   397                 }
       
   398 
       
   399                 int kind;
       
   400                 if (kindStr == null || kindStr.isEmpty() || kindStr.equals("default")) {
       
   401                     kind = IconDesc.ICON_KIND_DEFAULT;
       
   402                 } else if (kindStr.equals("shortcut")) {
       
   403                     kind = IconDesc.ICON_KIND_SHORTCUT;
       
   404                 } else {
       
   405                     Log.warning("Ignoring unsupported icon \"" + href + "\" with kind \"" + kindStr + "\".");
       
   406                     return;
       
   407                 }
       
   408 
       
   409                 answer.add(new IconDesc(href, kind));
       
   410             }
       
   411         });
       
   412         return answer.toArray(new IconDesc[answer.size()]);
       
   413     }
       
   414 
       
   415     private static ShortcutDesc getShortcutDesc(XMLNode e)
       
   416                 throws MissingFieldException, BadFieldException {
       
   417         final ArrayList<ShortcutDesc> shortcuts = new ArrayList<>();
       
   418 
       
   419         XMLUtils.visitElements(e, "<shortcut>", new XMLUtils.ElementVisitor() {
       
   420             @Override
       
   421             public void visitElement(XMLNode shortcutNode)
       
   422                 throws MissingFieldException, BadFieldException {
       
   423                 boolean desktopHinted =
       
   424                     XMLUtils.isElementPath(shortcutNode, "<desktop>");
       
   425                 boolean menuHinted =
       
   426                     XMLUtils.isElementPath(shortcutNode, "<menu>");
       
   427                 String submenuHinted =
       
   428                     XMLUtils.getAttribute(shortcutNode, "<menu>", "submenu");
       
   429                 shortcuts.add(new ShortcutDesc(desktopHinted, menuHinted, submenuHinted));
       
   430             }
       
   431         });
       
   432 
       
   433         if (shortcuts.size() > 0) {
       
   434             return shortcuts.get(0);
       
   435         }
       
   436         return null;
       
   437     }
       
   438 
       
   439     private static AssociationDesc[] getAssociationDesc(final String source,
       
   440         final URL codebase, XMLNode e)
       
   441                 throws MissingFieldException, BadFieldException {
       
   442         final ArrayList<AssociationDesc> answer = new ArrayList<>();
       
   443         XMLUtils.visitElements(e, "<association>",
       
   444             new XMLUtils.ElementVisitor() {
       
   445             @Override
       
   446             public void visitElement(XMLNode node)
       
   447                 throws MissingFieldException, BadFieldException {
       
   448 
       
   449                 String extensions = XMLUtils.getAttribute(
       
   450                                        node, "", "extensions");
       
   451 
       
   452                 String mimeType = XMLUtils.getAttribute(
       
   453                                        node, "", "mime-type");
       
   454                 String description = XMLUtils.getElementContents(
       
   455                                         node, "<description>");
       
   456 
       
   457                 URL icon = XMLUtils.getAttributeURL(
       
   458                                 source, codebase, node, "<icon>", "href");
       
   459 
       
   460                 if (!JNLPConverter.isIconSupported(icon.toExternalForm())) {
       
   461                     icon = null;
       
   462                 }
       
   463 
       
   464                 if (extensions == null && mimeType == null) {
       
   465                     throw new MissingFieldException(source,
       
   466                                  "<association>(<extensions><mime-type>)");
       
   467                 } else if (extensions == null) {
       
   468                     throw new MissingFieldException(source,
       
   469                                      "<association><extensions>");
       
   470                 } else if (mimeType == null) {
       
   471                     throw new MissingFieldException(source,
       
   472                                      "<association><mime-type>");
       
   473                 }
       
   474 
       
   475                 // don't support uppercase extension and mime-type on gnome.
       
   476                 if ("gnome".equals(System.getProperty("sun.desktop"))) {
       
   477                     extensions = extensions.toLowerCase();
       
   478                     mimeType = mimeType.toLowerCase();
       
   479                 }
       
   480 
       
   481                 answer.add(new AssociationDesc(extensions, mimeType,
       
   482                                                 description, icon));
       
   483             }
       
   484         });
       
   485         return answer.toArray(
       
   486                 new AssociationDesc[answer.size()]);
       
   487     }
       
   488 
       
   489     /** Handle the individual entries in a resource desc */
       
   490     private static void handleResourceElement(String source, URL codebase,
       
   491         XMLNode e, ResourcesDesc rdesc, boolean ignoreJres, String arch, JNLPDesc jnlpd)
       
   492         throws MissingFieldException, BadFieldException {
       
   493 
       
   494         String tag = e.getName();
       
   495 
       
   496         boolean matchArch = GeneralUtil.prefixMatchArch(
       
   497             GeneralUtil.getStringList(arch));
       
   498 
       
   499 
       
   500         if (matchArch && (tag.equals("jar") || tag.equals("nativelib"))) {
       
   501             /*
       
   502              * jar/nativelib elements
       
   503              */
       
   504             URL href = XMLUtils.getRequiredURL(source, codebase, e, "", "href");
       
   505             String version = XMLUtils.getAttribute(e, "", "version", null);
       
   506 
       
   507             String mainStr = XMLUtils.getAttribute(e, "", "main");
       
   508             boolean isNativeLib = tag.equals("nativelib");
       
   509 
       
   510             boolean isMain = "true".equalsIgnoreCase(mainStr);
       
   511 
       
   512             JARDesc jd = new JARDesc(href, version, isMain, isNativeLib, rdesc);
       
   513             rdesc.addResource(jd);
       
   514         } else if (matchArch && tag.equals("property")) {
       
   515             /*
       
   516              *  property tag
       
   517              */
       
   518             String name  = XMLUtils.getRequiredAttribute(source, e, "", "name");
       
   519             String value = XMLUtils.getRequiredAttributeEmptyOK(
       
   520                     source, e, "", "value");
       
   521 
       
   522             rdesc.addResource(new PropertyDesc(name, value));
       
   523         } else if (matchArch && tag.equals("extension")) {
       
   524             URL href = XMLUtils.getRequiredURL(source, codebase, e, "", "href");
       
   525             String version = XMLUtils.getAttribute(e, "", "version", null);
       
   526             rdesc.addResource(new ExtensionDesc(href, version));
       
   527         } else if ((tag.equals("java") || tag.equals("j2se")) && !ignoreJres) {
       
   528             /*
       
   529              * j2se element
       
   530              */
       
   531             String version  =
       
   532                 XMLUtils.getRequiredAttribute(source, e, "", "version");
       
   533             String minheapstr =
       
   534                 XMLUtils.getAttribute(e, "", "initial-heap-size");
       
   535             String maxheapstr =
       
   536                 XMLUtils.getAttribute(e, "", "max-heap-size");
       
   537 
       
   538             String vmargs =
       
   539                 XMLUtils.getAttribute(e, "", "java-vm-args");
       
   540 
       
   541             if (jnlpd.isJRESet()) {
       
   542                 if (vmargs == null) {
       
   543                     vmargs = "none";
       
   544                 }
       
   545                 Log.warning("Ignoring repeated element <" + tag + "> with version " + version +
       
   546                         " and java-vm-args: " + vmargs);
       
   547                 return;
       
   548             }
       
   549 
       
   550             long minheap = GeneralUtil.heapValToLong(minheapstr);
       
   551             long maxheap = GeneralUtil.heapValToLong(maxheapstr);
       
   552 
       
   553             ResourcesDesc cbs = null;
       
   554             buildResourcesDesc(source, codebase, e, true, null);
       
   555 
       
   556             // JRE
       
   557             JREDesc jreDesc = new JREDesc(
       
   558                 version,
       
   559                 minheap,
       
   560                 maxheap,
       
   561                 vmargs,
       
   562                 cbs,
       
   563                 arch);
       
   564 
       
   565             rdesc.addResource(jreDesc);
       
   566 
       
   567             jnlpd.setIsJRESet(true);
       
   568         }
       
   569     }
       
   570 
       
   571     /** Extract data from the application-desc tag */
       
   572     private static void buildApplicationDesc(final String source,
       
   573         XMLNode root, JNLPDesc jnlpd) throws MissingFieldException, BadFieldException {
       
   574 
       
   575         String mainclass = XMLUtils.getClassName(source, root,
       
   576                            "<application-desc>", "main-class", false);
       
   577         String appType = XMLUtils.getAttribute(root, "<application-desc>",
       
   578                                                "type", "Java");
       
   579         String progressclass  = XMLUtils.getClassName(source, root,
       
   580                                 "<application-desc>", "progress-class", false);
       
   581         if (progressclass != null && !progressclass.isEmpty()) {
       
   582             Log.warning("JNLPConverter does not support progress indication. \"" + progressclass + "\" will not be loaded and will be ignored.");
       
   583         }
       
   584 
       
   585         if (!("Java".equalsIgnoreCase(appType) ||
       
   586             "JavaFx".equalsIgnoreCase(appType))) {
       
   587             throw new BadFieldException(source, XMLUtils.getPathString(root) +
       
   588                 "<application-desc>type", appType);
       
   589         }
       
   590 
       
   591         if ("JavaFx".equalsIgnoreCase(appType)) {
       
   592             jnlpd.setIsFXApp(true);
       
   593         }
       
   594 
       
   595         XMLUtils.visitElements(root, "<application-desc><argument>", new XMLUtils.ElementVisitor() {
       
   596             @Override
       
   597             public void visitElement(XMLNode e) throws MissingFieldException, BadFieldException {
       
   598                 String arg = XMLUtils.getElementContents(e, "", null);
       
   599                 if (arg == null) {
       
   600                     throw new BadFieldException(source, XMLUtils.getPathString(e), "");
       
   601                 }
       
   602                 jnlpd.addArguments(arg);
       
   603             }
       
   604         });
       
   605 
       
   606         XMLUtils.visitElements(root, "<application-desc><param>",
       
   607             new XMLUtils.ElementVisitor() {
       
   608             @Override
       
   609             public void visitElement(XMLNode e) throws MissingFieldException,
       
   610                 BadFieldException {
       
   611                 String pn = XMLUtils.getRequiredAttribute(
       
   612                             source, e, "", "name");
       
   613                 String pv = XMLUtils.getRequiredAttributeEmptyOK(
       
   614                             source, e, "", "value");
       
   615                 jnlpd.setProperty(pn, pv);
       
   616             }
       
   617         });
       
   618         jnlpd.setMainClass(mainclass, false);
       
   619     }
       
   620 
       
   621     /** Extract data from the javafx-desc tag */
       
   622     private static void buildFXAppDesc(final String source,
       
   623         XMLNode root, String element, JNLPDesc jnlpd)
       
   624              throws MissingFieldException, BadFieldException {
       
   625         String mainclass = XMLUtils.getClassName(source, root, element,
       
   626                                                  "main-class", true);
       
   627         String name = XMLUtils.getRequiredAttribute(source, root,
       
   628                                         "<javafx-desc>", "name");
       
   629 
       
   630         /* extract arguments */
       
   631         XMLUtils.visitElements(root, "<javafx-desc><argument>", new XMLUtils.ElementVisitor() {
       
   632             @Override
       
   633             public void visitElement(XMLNode e) throws MissingFieldException, BadFieldException {
       
   634                 String arg = XMLUtils.getElementContents(e, "", null);
       
   635                 if (arg == null) {
       
   636                     throw new BadFieldException(source, XMLUtils.getPathString(e), "");
       
   637                 }
       
   638                 jnlpd.addArguments(arg);
       
   639             }
       
   640         });
       
   641 
       
   642         /* extract parameters */
       
   643         XMLUtils.visitElements(root, "<javafx-desc><param>",
       
   644             new XMLUtils.ElementVisitor() {
       
   645             @Override
       
   646             public void visitElement(XMLNode e) throws MissingFieldException,
       
   647                 BadFieldException {
       
   648                 String pn = XMLUtils.getRequiredAttribute(
       
   649                             source, e, "", "name");
       
   650                 String pv = XMLUtils.getRequiredAttributeEmptyOK(
       
   651                             source, e, "", "value");
       
   652                 jnlpd.setProperty(pn, pv);
       
   653             }
       
   654         });
       
   655 
       
   656         jnlpd.setMainClass(mainclass, true);
       
   657         jnlpd.setName(name);
       
   658     }
       
   659 }