Hello,
Here is a fix for PR955. [1]
This was quite a tricky patch to figure out. Proprietary webstart handles locales.. interestingly.. I've made ours use a fallback
mechanism to find any information in the information tag. For each item it searches for (e.g. the title), it will try to find an
information tag which has the closest possible locale that looks like your JVM's locale. Please see the unit tests for examples.
I have changed a few other things too with how we setup locales, the variant was not working properly. It was assumed to be 2
characters long which is definitely not the case. My locale is en_CA.utf8 <-- variant has 4 chars.
My changes to the localeMatches method cover both the implementation I needed (being able to match multiple a locale by a given
precision - the enum), as well as making it more easily understood. I hope the switch cases do this, it was a bit of a brain teaser
figuring out those if statements and double negatives. :/
All other changes are in the ChangeLog below:
+2012-08-01 Danesh Dadachanji <
ddadacha@...>
+
+ Fix PR955: regression: SweetHome3D fails to run
+ * NEWS: Added entry for PR955
+ * netx/net/sourceforge/jnlp/JNLPFile.java: New enum Match that represents
+ the level of precision to use when matching locales.
+ (localMatches): Renamed to localeMatches, added matchLevel paramater
+ and updated conditionals to handle the level of precision specified by it.
+ (getVendor): New method that returns an information's vendor text.
+ (getInformation): Added override methods for getTitle and getVendor
+ that are used by the anonymous class to filter by locale. All three
+ methods now go through all levels of precision to search for the best
+ fitted locale.
+ (getResources), (getResourcesDescs): Updated to check if any level of
+ precision matches when searching for locales.
+ (parse): Added call to checkForTitleVendor.
+ * netx/net/sourceforge/jnlp/Parser.java
+ (checkForTitleVendor): New method to check for availability of localized
+ title and vendor from the information tags. Throws ParseException.
+ (getInfo): Replace loop with foreach loop.
+ (getInformationDesc): Remove check for present title and vendor.
+ (getLocale): Variant returned can now use everything after the eigth
+ element of the locale's string.
+ * netx/net/sourceforge/jnlp/resources/Messages.properties:
+ Update missing title and vendor messages to mention localization.
+ * tests/reproducers/simple/InformationTitleVendorParser/testcases/InformationTitleVendorParserTest.java:
+ Update output string as per new changes to Messages internationalizations.
+ * tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java:
+ New unit test that checks the localesMatches method in JNLPFile.
+ * tests/netx/unit/net/sourceforge/jnlp/MockJNLPFile.java:
+ New class used to create a mock JNLPFile object.
+ * tests/netx/unit/net/sourceforge/jnlp/ParserTest.java:
+ New unit test that checks that the return of getTitle and getVendor
+ have localized information.
I would like to push this to HEAD and backport it to 1.3. The regression isn't present in 1.2 and before. Any thoughts?
Regards,
Danesh
[1]
http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=955[title-vendor-required-06.patch]
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,7 @@ New in release 1.3 (2012-XX-XX):
- RH838417: Disambiguate signed applet security prompt from certificate warning
- RH838559: Disambiguate signed applet security prompt from certificate warning
- RH720836: project can be compiled against GTK+ 2 or 3 librarie
+ - PR955: regression: SweetHome3D fails to run
New in release 1.2 (2011-XX-XX):
* Security updates:
diff --git a/netx/net/sourceforge/jnlp/JNLPFile.java b/netx/net/sourceforge/jnlp/JNLPFile.java
--- a/netx/net/sourceforge/jnlp/JNLPFile.java
+++ b/netx/net/sourceforge/jnlp/JNLPFile.java
@@ -99,18 +99,18 @@ public class JNLPFile {
/** the security descriptor */
protected SecurityDesc security;
- /** the default OS */
+ /** the default JVM locale */
protected Locale defaultLocale = null;
- /** the default arch */
+ /** the default OS */
protected String defaultOS = null;
- /** the default jvm */
+ /** the default arch */
protected String defaultArch = null;
-
+
/** A signed JNLP file is missing from the main jar */
private boolean missingSignedJNLP = false;
-
+
/** JNLP file contains special properties */
private boolean containsSpecialProperties = false;
@@ -118,7 +118,7 @@ public class JNLPFile {
* List of acceptable properties (not-special)
*/
private String[] generalProperties = SecurityDesc.getJnlpRIAPermissions();
-
+
{ // initialize defaults if security allows
try {
defaultLocale = Locale.getDefault();
@@ -129,6 +129,8 @@ public class JNLPFile {
}
}
+ static enum Match { LANG_COUNTRY_VARIANT, LANG_COUNTRY, LANG, GENERALIZED }
+
/**
* Empty stub, allowing child classes to override the constructor
*/
@@ -185,9 +187,9 @@ public class JNLPFile {
* @throws ParseException if the JNLP file was invalid
*/
public JNLPFile(URL location, Version version, boolean strict, UpdatePolicy policy) throws IOException, ParseException {
- this(location, version, strict, policy, null);
+ this(location, version, strict, policy, null);
}
-
+
/**
* Create a JNLPFile from a URL and a version, checking for updates
* using the specified policy.
@@ -284,7 +286,7 @@ public class JNLPFile {
}
/**
- * Returns the JNLP file's title. This method returns the same
+ * Returns the JNLP file's best localized title. This method returns the same
* value as InformationDesc.getTitle().
*/
public String getTitle() {
@@ -292,6 +294,14 @@ public class JNLPFile {
}
/**
+ * Returns the JNLP file's best localized vendor. This method returns the same
+ * value as InformationDesc.getVendor().
+ */
+ public String getVendor() {
+ return getInformation().getVendor();
+ }
+
+ /**
* Returns the JNLP file's network location as specified in the
* JNLP file.
*/
@@ -352,14 +362,46 @@ public class JNLPFile {
protected List<Object> getItems(Object key) {
List<Object> result = new ArrayList<Object>();
- for (int i = 0; i < info.size(); i++) {
- InformationDesc infoDesc = info.get(i);
+ for (Match precision : Match.values()) {
+ for (InformationDesc infoDesc : JNLPFile.this.info) {
+ if (localeMatches(locale, infoDesc.getLocales(), precision)) {
+ result.addAll(infoDesc.getItems(key));
+ }
+ }
- if (localMatches(locale, infoDesc.getLocales()))
- result.addAll(infoDesc.getItems(key));
+ if (result.size() > 0) {
+ return result;
+ }
+ }
+ return result;
+ }
+
+ public String getTitle() {
+ for (Match precision : Match.values()) {
+ for (InformationDesc infoDesc : JNLPFile.this.info) {
+ String title = infoDesc.getTitle();
+ if (localeMatches(locale, infoDesc.getLocales(), precision)
+ && title != null && !"".equals(title)) {
+ return title;
+ }
+ }
}
- return result;
+ return null;
+ }
+
+ public String getVendor() {
+ for (Match precision : Match.values()) {
+ for (InformationDesc infoDesc : JNLPFile.this.info) {
+ String vendor = infoDesc.getVendor();
+ if (localeMatches(locale, infoDesc.getLocales(), precision)
+ && vendor != null && !"".equals(vendor)) {
+ return vendor;
+ }
+ }
+ }
+
+ return null;
}
};
}
@@ -397,7 +439,11 @@ public class JNLPFile {
List<T> result = new ArrayList<T>();
for (ResourcesDesc rescDesc : resources) {
- if (localMatches(locale, rescDesc.getLocales())
+ boolean hasUsableLocale = false;
+ for (Match match : Match.values()) {
+ hasUsableLocale |= localeMatches(locale, rescDesc.getLocales(), match);
+ }
+ if (hasUsableLocale
&& stringMatches(os, rescDesc.getOS())
&& stringMatches(arch, rescDesc.getArch()))
result.addAll(rescDesc.getResources(launchType));
@@ -433,7 +479,11 @@ public class JNLPFile {
public ResourcesDesc[] getResourcesDescs(final Locale locale, final String os, final String arch) {
List<ResourcesDesc> matchingResources = new ArrayList<ResourcesDesc>();
for (ResourcesDesc rescDesc: resources) {
- if (localMatches(locale, rescDesc.getLocales())
+ boolean hasUsableLocale = false;
+ for (Match match : Match.values()) {
+ hasUsableLocale |= localeMatches(locale, rescDesc.getLocales(), match);
+ }
+ if (hasUsableLocale
&& stringMatches(os, rescDesc.getOS())
&& stringMatches(arch, rescDesc.getArch())) {
matchingResources.add(rescDesc);
@@ -546,28 +596,48 @@ public class JNLPFile {
*
* @param requested the local
* @param available the available locales
+ * @param precision the depth with which to match locales. 1 checks only
+ * language, 2 checks language and country, 3 checks language, country and
+ * variant for matches. Passing 0 will always return true.
* @return true if requested matches any of available, or if
* available is empty or null.
*/
- private boolean localMatches(Locale requested, Locale available[]) {
- if (available == null || available.length == 0)
- return true;
+ boolean localeMatches(Locale requested, Locale available[], Match matchLevel) {
- for (int i = 0; i < available.length; i++) {
- String language = requested.getLanguage(); // "" but never null
- String country = requested.getCountry();
- String variant = requested.getVariant();
+ if (matchLevel == Match.GENERALIZED)
+ return available == null || available.length == 0;
- if (!"".equals(language) && !language.equalsIgnoreCase(available[i].getLanguage()))
- continue;
- if (!"".equals(country) && !country.equalsIgnoreCase(available[i].getCountry()))
- continue;
- if (!"".equals(variant) && !variant.equalsIgnoreCase(available[i].getVariant()))
- continue;
+ String language = requested.getLanguage(); // "" but never null
+ String country = requested.getCountry();
+ String variant = requested.getVariant();
- return true;
+ for (Locale locale : available) {
+ switch (matchLevel) {
+ case LANG:
+ if (!language.isEmpty()
+ && language.equals(locale.getLanguage())
+ && locale.getCountry().isEmpty()
+ && locale.getVariant().isEmpty())
+ return true;
+ break;
+ case LANG_COUNTRY:
+ if (!language.isEmpty()
+ && language.equals(locale.getLanguage())
+ && !country.isEmpty()
+ && country.equals(locale.getCountry())
+ && locale.getVariant().isEmpty())
+ return true;
+ break;
+ case LANG_COUNTRY_VARIANT:
+ if (language.equals(locale.getLanguage())
+ && country.equals(locale.getCountry())
+ && variant.equals(locale.getVariant()))
+ return true;
+ break;
+ default:
+ break;
+ }
}
-
return false;
}
@@ -612,14 +682,15 @@ public class JNLPFile {
codeBase = parser.getCodeBase();
sourceLocation = parser.getFileLocation() != null ? parser.getFileLocation() : location;
info = parser.getInfo(root);
+ parser.checkForTitleVendor();
update = parser.getUpdate(root);
resources = parser.getResources(root, false); // false == not a j2se/java resources section
launchType = parser.getLauncher(root);
component = parser.getComponent(root);
security = parser.getSecurity(root);
-
+
checkForSpecialProperties();
-
+
} catch (ParseException ex) {
throw ex;
} catch (Exception ex) {
@@ -729,7 +800,7 @@ public class JNLPFile {
/**
* Returns a boolean after determining if a signed JNLP warning should be
* displayed in the 'More Information' panel.
- *
+ *
* @return true if a warning should be displayed; otherwise false
*/
public boolean requiresSignedJNLPWarning() {
@@ -742,5 +813,4 @@ public class JNLPFile {
public void setSignedJNLPAsMissing() {
missingSignedJNLP = true;
}
-
}
diff --git a/netx/net/sourceforge/jnlp/Parser.java b/netx/net/sourceforge/jnlp/Parser.java
--- a/netx/net/sourceforge/jnlp/Parser.java
+++ b/netx/net/sourceforge/jnlp/Parser.java
@@ -1,5 +1,5 @@
// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
-// Copyright (C) 2009 Red Hat, Inc.
+// Copyright (C) 2012 Red Hat, Inc.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
@@ -424,6 +424,21 @@ class Parser {
// This section loads the information elements
//
+
+ /**
+ * Make sure a title and vendor are present and nonempty and localized as
+ * best matching as possible for the JVM's current locale.
+ * @throws ParseException
+ */
+ void checkForTitleVendor() throws ParseException {
+ String title = file.getTitle();
+ String vendor = file.getVendor();
+ if (title == null || title.trim().isEmpty())
+ throw new ParseException(R("PNoTitleElement"));
+ if (vendor == null || vendor.trim().isEmpty())
+ throw new ParseException(R("PNoVendorElement"));
+ }
+
/**
* Returns all of the information elements under the specified
* node.
@@ -441,8 +456,9 @@ class Parser {
throw new ParseException(R("PNoInfoElement"));
// create objects from the info sections
- for (int i = 0; i < info.length; i++)
- result.add(getInformationDesc(info[i]));
+ for (Node infoNode : info) {
+ result.add(getInformationDesc(infoNode));
+ }
return result;
}
@@ -504,11 +520,6 @@ class Parser {
child = child.getNextSibling();
}
- if (info.getTitle() == null || info.getTitle().trim().isEmpty())
- throw new ParseException(R("PNoTitleElement"));
- if (info.getVendor() == null || info.getVendor().trim().isEmpty())
- throw new ParseException(R("PNoVendorElement"));
-
return info;
}
@@ -896,7 +907,7 @@ class Parser {
String language = localeStr.substring(0, 2);
String country = (localeStr.length() < 5) ? "" : localeStr.substring(3, 5);
- String variant = (localeStr.length() < 7) ? "" : localeStr.substring(6, 8);
+ String variant = (localeStr.length() > 7) ? localeStr.substring(6) : "";
// null is not allowed n locale but "" is
return new Locale(language, country, variant);
diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties
@@ -106,9 +106,9 @@ PExtensionHasJ2SE=j2se element cannot be
PInnerJ2SE=j2se element cannot be specified within a j2se element.
PTwoMains=Duplicate main JAR defined in a resources element (there can be only one)
PNativeHasMain=Cannot specify main attribute on native JARs.
-PNoInfoElement=No information section defined
-PNoTitleElement=The title section has not been defined in the JNLP file.
-PNoVendorElement=The vendor section has not been defined in the JNLP file.
+PNoInfoElement=No information section defined.
+PNoTitleElement=The title section has not been defined for your locale in the JNLP file.
+PNoVendorElement=The vendor section has not been defined for your locale in the JNLP file.
PTwoDescriptions=Duplicate description of kind {0}
PSharing=Element "sharing-allowed" is illegal in a standard JNLP file
PTwoSecurity=Only one security element allowed per JNLPFile.
diff --git a/tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java b/tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java
new file mode 100644
--- /dev/null
+++ b/tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java
@@ -0,0 +1,105 @@
+/* JNLPFileTest.java
+ Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package net.sourceforge.jnlp;
+
+import java.util.Locale;
+
+import net.sourceforge.jnlp.JNLPFile.Match;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class JNLPFileTest {
+ Locale jvmLocale = new Locale("en", "CA", "utf8");
+ MockJNLPFile file = new MockJNLPFile(jvmLocale);
+
+ @Test
+ public void testCompareAll() {
+ Locale[] correctAvailable = { new Locale("en", "CA", "utf8") };
+ Assert.assertTrue("Entire locale should match but did not.",
+ file.localeMatches(jvmLocale, correctAvailable, Match.LANG_COUNTRY_VARIANT));
+
+ Locale[] mismatchedAvailable = { new Locale("en", "CA", "utf16") };
+ Assert.assertFalse("Should not match variant but did.",
+ file.localeMatches(jvmLocale, mismatchedAvailable, Match.LANG_COUNTRY_VARIANT));
+ }
+
+ @Test
+ public void testLangAndCountry() {
+ Locale[] correctAvailable = { new Locale("en", "CA") };
+ Assert.assertTrue("Should match language and country, ignoring variant but did not.",
+ file.localeMatches(jvmLocale, correctAvailable, Match.LANG_COUNTRY));
+
+ Locale[] mismatchedAvailable = { new Locale("en", "EN") };
+ Assert.assertFalse("Should not match country but did.",
+ file.localeMatches(jvmLocale, mismatchedAvailable, Match.LANG_COUNTRY));
+
+ Locale[] extraMismatched = { new Locale("en", "CA", "utf16") };
+ Assert.assertFalse("Should not match because of extra variant but did.",
+ file.localeMatches(jvmLocale, extraMismatched, Match.LANG_COUNTRY));
+ }
+
+ @Test
+ public void testLangOnly() {
+ Locale[] correctAvailable = { new Locale("en") };
+ Assert.assertTrue("Should match only language but did not.",
+ file.localeMatches(jvmLocale, correctAvailable, Match.LANG));
+
+ Locale[] mismatchedAvailable = { new Locale("fr", "CA", "utf8") };
+ Assert.assertFalse("Should not match language but did.",
+ file.localeMatches(jvmLocale, mismatchedAvailable, Match.LANG));
+
+ Locale[] extraMismatched = { new Locale("en", "EN") };
+ Assert.assertFalse("Should not match because of extra country but did.",
+ file.localeMatches(jvmLocale, extraMismatched, Match.LANG));
+ }
+
+ @Test
+ public void testNoLocalAvailable() {
+ Assert.assertTrue("Null locales should match but did not.",
+ file.localeMatches(jvmLocale, null, Match.GENERALIZED));
+
+ Locale[] emptyAvailable = {};
+ Assert.assertTrue("Empty locales list should match but did not.",
+ file.localeMatches(jvmLocale, emptyAvailable, Match.GENERALIZED));
+
+ Locale[] mismatchAvailable = { new Locale("fr", "FR", "utf16") };
+ Assert.assertFalse("Locales list should not match generalized case but did.",
+ file.localeMatches(jvmLocale, mismatchAvailable, Match.GENERALIZED));
+ }
+}
diff --git a/tests/netx/unit/net/sourceforge/jnlp/MockJNLPFile.java b/tests/netx/unit/net/sourceforge/jnlp/MockJNLPFile.java
new file mode 100644
--- /dev/null
+++ b/tests/netx/unit/net/sourceforge/jnlp/MockJNLPFile.java
@@ -0,0 +1,52 @@
+/* MockJNLPFile.java
+ Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package net.sourceforge.jnlp;
+
+import java.util.List;
+import java.util.Locale;
+
+public class MockJNLPFile extends JNLPFile {
+
+ public MockJNLPFile(Locale locale) {
+ defaultLocale = locale;
+ }
+
+ public void setInfo(List<InformationDesc> infoList) {
+ info = infoList;
+ }
+}
diff --git a/tests/netx/unit/net/sourceforge/jnlp/ParserTest.java b/tests/netx/unit/net/sourceforge/jnlp/ParserTest.java
new file mode 100644
--- /dev/null
+++ b/tests/netx/unit/net/sourceforge/jnlp/ParserTest.java
@@ -0,0 +1,532 @@
+/* ParserTest.java
+ Copyright (C) 2012 Red Hat, Inc.
+
+This file is part of IcedTea.
+
+IcedTea is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License as published by
+the Free Software Foundation, version 2.
+
+IcedTea is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with IcedTea; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301 USA.
+
+Linking this library statically or dynamically with other modules is
+making a combined work based on this library. Thus, the terms and
+conditions of the GNU General Public License cover the whole
+combination.
+
+As a special exception, the copyright holders of this library give you
+permission to link this library with independent modules to produce an
+executable, regardless of the license terms of these independent
+modules, and to copy and distribute the resulting executable under
+terms of your choice, provided that you also meet, for each linked
+independent module, the terms and conditions of the license of that
+module. An independent module is a module which is not derived from
+or based on this library. If you modify this library, you may extend
+this exception to your version of the library, but you are not
+obligated to do so. If you do not wish to do so, delete this
+exception statement from your version.
+ */
+
+package net.sourceforge.jnlp;
+
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/** Test various corner cases of the parser */
+public class ParserTest {
+
+ private static final String LANG = "en";
+ private static final String COUNTRY = "CA";
+ private static final String VARIANT = "utf8";
+ private static final Locale LOCALE = new Locale(LANG, COUNTRY, VARIANT);
+
+ @Test(expected = ParseException.class)
+ public void testMissingInfo() throws ParseException {
+ String data = "<jnlp></jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ parser.getInfo(root);
+ }
+
+ @Test(expected = ParseException.class)
+ public void testEmptyLocalizedInfo() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information locale='" + LANG + "_" + COUNTRY + "." + VARIANT + "'>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = new ArrayList<InformationDesc>();
+ try {
+ infoDescs.addAll(parser.getInfo(root));
+ } catch (ParseException pe) {
+ Assert.fail(pe.getMessage());
+ }
+
+ Assert.assertTrue("Exactly one info desc should be found", infoDescs.size() == 1);
+
+ file.setInfo(infoDescs);
+ parser.checkForTitleVendor();
+ }
+
+ @Test
+ public void testOneFullyLocalizedInfo() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information locale='" + LANG + "_" + COUNTRY + "." + VARIANT + "'>\n"
+ + " <title>English_CA_utf8_T</title>\n"
+ + " <vendor>English_CA_utf8_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+
+ Assert.assertTrue("Exactly one info desc should be found", infoDescs.size() == 1);
+
+ file.setInfo(infoDescs);
+
+ Assert.assertEquals("Title should be `English_CA_utf8_T' but wasn't",
+ "English_CA_utf8_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `English_CA_utf8_V' but wasn't",
+ "English_CA_utf8_V", file.getVendor());
+ }
+
+ @Test
+ public void testOneLangCountryLocalizedInfo() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='" + LANG + "_" + COUNTRY + "'>\n"
+ + " <title>English_CA_T</title>\n"
+ + " <vendor>English_CA_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+ Assert.assertTrue("Exactly two info descs should be found", infoDescs.size() == 2);
+
+ file.setInfo(infoDescs);
+ Assert.assertEquals("Title should be `English_CA_T' but wasn't",
+ "English_CA_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `English_CA_V' but wasn't",
+ "English_CA_V", file.getVendor());
+ }
+
+ @Test
+ public void testOneLangLocalizedInfo() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='" + LANG + "'>\n"
+ + " <title>English_T</title>\n"
+ + " <vendor>English_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+ Assert.assertTrue("Exactly two info descs should be found", infoDescs.size() == 2);
+
+ file.setInfo(infoDescs);
+ Assert.assertEquals("Title should be `English_T' but wasn't",
+ "English_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `English_V' but wasn't",
+ "English_V", file.getVendor());
+ }
+
+ @Test
+ public void testGeneralizedInfo() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+ Assert.assertTrue("Exactly one info desc should be found", infoDescs.size() == 1);
+
+ file.setInfo(infoDescs);
+ Assert.assertEquals("Title should be `Generalized_T' but wasn't",
+ "Generalized_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `Generalized_V' but wasn't",
+ "Generalized_V", file.getVendor());
+ }
+
+ @Test
+ public void testTwoDifferentLocalizedInfo() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en'>\n"
+ + " <title>English_T</title>\n"
+ + " <vendor>English_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='fr'>\n"
+ + " <title>French_T</title>\n"
+ + " <vendor>French_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+ Assert.assertTrue("Exactly three info descs should be found", infoDescs.size() == 3);
+
+ file.setInfo(infoDescs);
+ Assert.assertEquals("Title should be `English_T' but wasn't",
+ "English_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `English_V' but wasn't",
+ "English_V", file.getVendor());
+ }
+
+ @Test
+ public void testTwoLocalizedWithSameLangInfo() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en'>\n"
+ + " <title>English_T</title>\n"
+ + " <vendor>English_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en_CA'>\n"
+ + " <title>English_CA_T</title>\n"
+ + " <vendor>English_CA_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+ Assert.assertTrue("Exactly three info descs should be found", infoDescs.size() == 3);
+
+ file.setInfo(infoDescs);
+ Assert.assertEquals("Title should be `English_CA_T' but wasn't",
+ "English_CA_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `English_CA_V' but wasn't",
+ "English_CA_V", file.getVendor());
+ }
+
+ @Test
+ public void testTwoSameLangOneMissingTitle() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en'>\n"
+ + " <title>English_T</title>\n"
+ + " <vendor>English_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en_CA'>\n"
+ + " <vendor>English_CA_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+ Assert.assertTrue("Exactly three info descs should be found", infoDescs.size() == 3);
+
+ file.setInfo(infoDescs);
+ Assert.assertEquals("Title should be `English_T' but wasn't",
+ "English_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `English_CA_V' but wasn't",
+ "English_CA_V", file.getVendor());
+ }
+
+ @Test
+ public void testTwoSameLangWithGeneralizedTitle() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en'>\n"
+ + " <vendor>English_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en_CA'>\n"
+ + " <vendor>English_CA_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+ Assert.assertTrue("Exactly three info descs should be found", infoDescs.size() == 3);
+
+ file.setInfo(infoDescs);
+ Assert.assertEquals("Title should be `Generalized_T' but wasn't",
+ "Generalized_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `English_CA_V' but wasn't",
+ "English_CA_V", file.getVendor());
+ }
+
+ @Test(expected = ParseException.class)
+ public void testMissingTitle() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en'>\n"
+ + " <vendor>English_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='en_CA'>\n"
+ + " <vendor>English_CA_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = new ArrayList<InformationDesc>();
+ try {
+ infoDescs.addAll(parser.getInfo(root));
+ } catch (ParseException pe) {
+ Assert.fail(pe.getMessage());
+ }
+
+ Assert.assertTrue("Exactly three info descs should be found", infoDescs.size() == 3);
+
+ file.setInfo(infoDescs);
+ parser.checkForTitleVendor();
+ }
+
+ @Test(expected = ParseException.class)
+ public void testMissingVendor() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " </information>\n"
+ + " <information locale='en'>\n"
+ + " <title>English_T</title>\n"
+ + " </information>\n"
+ + " <information locale='en_CA'>\n"
+ + " <title>English_CA_T</title>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = new ArrayList<InformationDesc>();
+ try {
+ infoDescs.addAll(parser.getInfo(root));
+ } catch (ParseException pe) {
+ Assert.fail(pe.getMessage());
+ }
+
+ Assert.assertTrue("Exactly three info descs should be found", infoDescs.size() == 3);
+
+ file.setInfo(infoDescs);
+ parser.checkForTitleVendor();
+ }
+
+ @Test(expected = ParseException.class)
+ public void testMissingLocalizedTitle() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='fr'>\n"
+ + " <vendor>English_CA_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = new ArrayList<InformationDesc>();
+ try {
+ infoDescs.addAll(parser.getInfo(root));
+ } catch (ParseException pe) {
+ Assert.fail(pe.getMessage());
+ }
+
+ Assert.assertTrue("Exactly two info descs should be found", infoDescs.size() == 2);
+
+ file.setInfo(infoDescs);
+ parser.checkForTitleVendor();
+ }
+
+ @Test(expected = ParseException.class)
+ public void testMissingLocalizedVendor() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " </information>\n"
+ + " <information locale='fr'>\n"
+ + " <title>English_CA_T</title>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = new ArrayList<InformationDesc>();
+ try {
+ infoDescs.addAll(parser.getInfo(root));
+ } catch (ParseException pe) {
+ Assert.fail(pe.getMessage());
+ }
+
+ Assert.assertTrue("Exactly two info descs should be found",infoDescs.size() == 2);
+
+ file.setInfo(infoDescs);
+ parser.checkForTitleVendor();
+ }
+
+ @Test(expected = ParseException.class)
+ public void testEmptyLocalizedTitle() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information locale='" + LANG + "_" + COUNTRY + "." + VARIANT + "'>\n"
+ + " <title></title>\n"
+ + " <vendor>English_CA_utf8_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = new ArrayList<InformationDesc>();
+ try {
+ infoDescs.addAll(parser.getInfo(root));
+ } catch (ParseException pe) {
+ Assert.fail(pe.getMessage());
+ }
+
+ Assert.assertTrue("Exactly one info desc should be found", infoDescs.size() == 1);
+
+ file.setInfo(infoDescs);
+ parser.checkForTitleVendor();
+ }
+
+ @Test(expected = ParseException.class)
+ public void testEmptyLocalizedVendor() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information locale='" + LANG + "_" + COUNTRY + "." + VARIANT + "'>\n"
+ + " <title>English_CA_utf8_T</title>\n"
+ + " <vendor></vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = new ArrayList<InformationDesc>();
+ try {
+ infoDescs.addAll(parser.getInfo(root));
+ } catch (ParseException pe) {
+ Assert.fail(pe.getMessage());
+ }
+
+ Assert.assertTrue("Exactly one info desc should be found", infoDescs.size() == 1);
+
+ file.setInfo(infoDescs);
+ parser.checkForTitleVendor();
+ }
+
+ @Test
+ public void testFallbackEmptyLocalizedTitleVendor() throws ParseException {
+ String data = "<jnlp>\n"
+ + " <information>\n"
+ + " <title>Generalized_T</title>\n"
+ + " <vendor>Generalized_V</vendor>\n"
+ + " </information>\n"
+ + " <information locale='" + LANG + "'>\n"
+ + " <title>English_T</title>\n"
+ + " <vendor></vendor>\n"
+ + " </information>\n"
+ + " <information locale='" + LANG + "_" + COUNTRY + "'>\n"
+ + " <title></title>\n"
+ + " <vendor></vendor>\n"
+ + " </information>\n"
+ + " <information locale='" + LANG + "_" + COUNTRY + "." + VARIANT + "'>\n"
+ + " <title></title>\n"
+ + " <vendor></vendor>\n"
+ + " </information>\n"
+ + " <information locale='fr_" + COUNTRY + "." + VARIANT + "'>\n"
+ + " <title>French_CA_utf8_T</title>\n"
+ + " <vendor>French_CA_utf8_V</vendor>\n"
+ + " </information>\n"
+ + "</jnlp>\n";
+
+ Node root = Parser.getRootNode(new ByteArrayInputStream(data.getBytes()));
+ Assert.assertEquals("Root name is not jnlp", "jnlp", root.getNodeName());
+
+ MockJNLPFile file = new MockJNLPFile(LOCALE);
+ Parser parser = new Parser(file, null, root, false, false);
+ List<InformationDesc> infoDescs = parser.getInfo(root);
+
+ Assert.assertTrue("Exactly five info descs should be found", infoDescs.size() == 5);
+
+ file.setInfo(infoDescs);
+
+ Assert.assertEquals("Title should be `English_T' but wasn't",
+ "English_T", file.getTitle());
+ Assert.assertEquals("Vendor should be `Generalized_V' but wasn't",
+ "Generalized_V", file.getVendor());
+
+ parser.checkForTitleVendor();
+ }
+}
diff --git a/tests/reproducers/simple/InformationTitleVendorParser/testcases/InformationTitleVendorParserTest.java b/tests/reproducers/simple/InformationTitleVendorParser/testcases/InformationTitleVendorParserTest.java
--- a/tests/reproducers/simple/InformationTitleVendorParser/testcases/InformationTitleVendorParserTest.java
+++ b/tests/reproducers/simple/InformationTitleVendorParser/testcases/InformationTitleVendorParserTest.java
@@ -62,16 +62,16 @@ public class InformationTitleVendorParse
@Test
public void testTitleParser() throws Exception {
- runTest("TitleParser", "The title section has not been defined in the JNLP file.");
+ runTest("TitleParser", "The title section has not been defined for your locale in the JNLP file.");
}
@Test
public void testVendorParser() throws Exception {
- runTest("VendorParser", "The vendor section has not been defined in the JNLP file.");
+ runTest("VendorParser", "The vendor section has not been defined for your locale in the JNLP file.");
}
@Test
public void testTitleVendorParser() throws Exception {
// Note that the title message missing causes an immediate exception, regardless of Vendor.
- runTest("TitleVendorParser", "The title section has not been defined in the JNLP file.");
+ runTest("TitleVendorParser", "The title section has not been defined for your locale in the JNLP file.");
}
}