[RFC][icedtea-web]: Fix PR1166 - Embedded JNLP File is not supported in applet tag
Adam Domurad
adomurad at redhat.com
Tue Oct 9 11:43:40 PDT 2012
On 10/03/2012 02:10 PM, Saad Mohammad wrote:
> Hi Adam,
>
> Thanks for looking over my patches. I updated the reproducers after your review.
> Along with the attached reproducer, I also added unit test and updated the bug
> fix patch so it is more compatible with tests.
>
> Also, just a note, the reproducers do all pass for me through the test engine.
> Let me know if you are having any trouble.
>
> Thanks.
>
> CHANGELOGS:
> ==============================================================================
> BUG FIX:
>
> 2012-10-03 Saad Mohammad<smohammad at redhat.com>
>
> Fix PR1166: Embedded JNLP File is not supported in applet tag.
> * configure.ac: Checks for sun.misc.BASE64Encoder and
> sun.misc.BASE64Decoder
> * netx/net/sourceforge/jnlp/JNLPFile.java (JNLPFile):
> New constructor which accepts inputstream of jnlp file and a
> specified codebase.
> * netx/net/sourceforge/jnlp/Parser.java (Parser): If parsing of
> codebase fails, it will overwrite the codebase with the one passed
> in through parameters.
> * netx/net/sourceforge/jnlp/PluginBridge.java:
> (PluginBridge) Supports embedded jnlp file.
> (decodeBase64String) Decodes Base64 strings to byte array.
> ==============================================================================
> REPRODUCER:
>
> 2012-10-03 Saad Mohammad<smohammad at redhat.com>
>
> Added reproducer for PR1166.
> * tests/reproducers/simple/EmbeddedJnlpInApplet/resources/EmbeddedJnlp.jnlp:
> Launching jnlp file that is used by jnlp_href in applet tag
> *
> tests/reproducers/simple/EmbeddedJnlpInApplet/resources/EmbeddedJnlpInAppletNoCodebase.html:
> Applet with an embedded jnlp file with no codebase specified
> *
> tests/reproducers/simple/EmbeddedJnlpInApplet/resources/EmbeddedJnlpInAppletWithDotCodebase.html:
> Applet with an embedded jnlp file with codebase set as a 'dot'
> * tests/reproducers/simple/EmbeddedJnlpInApplet/resources/JnlpInApplet.html:
> Applet with jnlp_href file.
> * tests/reproducers/simple/EmbeddedJnlpInApplet/srcs/EmbeddedJnlp.java:
> Simple class that outputs strings.
> *
> tests/reproducers/simple/EmbeddedJnlpInApplet/testcases/EmbeddedJnlpInAppletTest.java:
> Testcase that tests embedded jnlps in html pages.
>
> ==============================================================================
> UNIT TESTS:
>
> 2012-10-03 Saad Mohammad<smohammad at redhat.com>
>
> * tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java:
> Tests the JNLPFile constructor that accepts an InputStream and an alternative
> codebase.
> * tests/netx/unit/net/sourceforge/jnlp/ParserTest.java:
> Tests if the constructor handles the alternative codebase parameter correctly.
> * tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java:
> Tests if BASE64 strings are decoded correctly and if PluginBridge is
> constructed with an
> embedded jnlp.
>
> ==============================================================================
>
Review of bugfix & unit test:
> diff --git a/configure.ac b/configure.ac
> --- a/configure.ac
> +++ b/configure.ac
> @@ -77,6 +77,8 @@
> IT_CHECK_FOR_CLASS(SUN_NET_WWW_PROTOCOL_JAR_URLJARFILECALLBACK,
> [sun.net.www.protocol.jar.URLJarFileCallBack])
> IT_CHECK_FOR_CLASS(SUN_AWT_X11_XEMBEDDEDFRAME,
> [sun.awt.X11.XEmbeddedFrame])
> IT_CHECK_FOR_CLASS(SUN_MISC_REF, [sun.misc.Ref])
> +IT_CHECK_FOR_CLASS(SUN_MISC_BASE64ENCODER, [sun.misc.BASE64Encoder])
> +IT_CHECK_FOR_CLASS(SUN_MISC_BASE64DECODER, [sun.misc.BASE64Decoder])
It's neither here nor there, but I wonder if these classes will still be
available here once http://openjdk.java.net/jeps/135 rolls around.
> IT_CHECK_FOR_CLASS(COM_SUN_JNDI_TOOLKIT_URL_URLUTIL,
> [com.sun.jndi.toolkit.url.UrlUtil])
> IT_CHECK_FOR_CLASS(SUN_APPLET_APPLETIMAGEREF,
> [sun.applet.AppletImageRef])
> IT_CHECK_FOR_APPLETVIEWERPANEL_HOLE
> 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
> @@ -255,6 +255,19 @@
> }
>
> /**
> + * Create a JNLPFile from an input stream.
> + *
> + * @param input input stream of JNLP file.
> + * @param codebase codebase to use if not specified in JNLP file..
> + * @param strict whether to enforce the spec rules
> + * @throws IOException if an IO exception occurred
> + * @throws ParseException if the JNLP file was invalid
> + */
> + public JNLPFile(InputStream input, URL codebase, boolean strict)
> throws ParseException {
> + parse(Parser.getRootNode(input), strict, null, codebase);
> + }
> +
>
It could be worth having the other version of this method (that always
passes a 'null' codebase) call this one.
> + /**
> * Create a JNLPFile from a character stream.
> *
> * @param input the stream
> 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
> @@ -143,9 +143,16 @@
>
> // JNLP tag information
> this.spec = getVersion(root, "spec", "1.0+");
> - this.codebase = addSlash(getURL(root, "codebase", base));
> - if (this.codebase == null) // We only override it if it is
> not specified.
> +
> + try {
> + this.codebase = addSlash(getURL(root, "codebase", base));
> + } catch (ParseException e) {
> + //If parsing fails, continue by overriding the codebase
> with the one passed in
> + }
> +
> + if (this.codebase == null) // Codebase is overwritten if
> codebase was not specified in file or if parsing of it failed
> this.codebase = codebase;
> +
> this.base = (this.codebase != null) ? this.codebase : base;
> // if codebase not specified use default codebase
> fileLocation = getURL(root, "href", this.base);
>
> diff --git a/netx/net/sourceforge/jnlp/PluginBridge.java
> b/netx/net/sourceforge/jnlp/PluginBridge.java
> --- a/netx/net/sourceforge/jnlp/PluginBridge.java
> +++ b/netx/net/sourceforge/jnlp/PluginBridge.java
> @@ -22,7 +22,10 @@
>
> package net.sourceforge.jnlp;
>
> +import java.io.ByteArrayInputStream;
> import java.io.File;
> +import java.io.IOException;
> +import java.io.InputStream;
> import java.net.URL;
> import java.net.MalformedURLException;
> import java.util.HashSet;
> @@ -32,6 +35,8 @@
> import java.util.Map;
> import java.util.Set;
>
> +import sun.misc.BASE64Decoder;
> +
> import net.sourceforge.jnlp.runtime.JNLPRuntime;
>
> /**
> @@ -96,7 +101,17 @@
> // Use codeBase as the context for the URL. If
> jnlp_href's
> // value is a complete URL, it will replace
> codeBase's context.
> URL jnlp = new URL(codeBase, atts.get("jnlp_href"));
> - JNLPFile jnlpFile = jnlpCreator.create(jnlp, null,
> false, JNLPRuntime.getDefaultUpdatePolicy(), codeBase);
> + JNLPFile jnlpFile = null;
> +
> + if (atts.containsKey("jnlp_embedded")) {
> + InputStream jnlpInputStream = new
> ByteArrayInputStream(decodeBase64String(atts.get("jnlp_embedded")));
> + jnlpFile = new JNLPFile(jnlpInputStream,
> codeBase, false);
> + } else
> + jnlpFile = jnlpCreator.create(jnlp, null, false,
> JNLPRuntime.getDefaultUpdatePolicy(), codeBase);
I'd prefer consistent {} around the cases here, it looks odd to me to
have one case wrapped with {} and one bare. (but then again I always
prefer {})
> +
> + if (jnlpFile.isApplet())
> + main = jnlpFile.getApplet().getMainClass();
Considering these two lines are new, could they safely be part of the
'containsKey("jnlp_embedded") ' case ? It'd be a little clearer in my
opinion.
> +
> Map<String, String> jnlpParams =
> jnlpFile.getApplet().getParameters();
> info = jnlpFile.info;
>
> @@ -349,4 +364,12 @@
> public boolean isInstaller() {
> return false;
> }
> +
> + /**
> + * Returns the decoded BASE64 string
> + */
> + public static byte[] decodeBase64String(String encodedString)
> throws IOException {
> + BASE64Decoder base64 = new BASE64Decoder();
> + return base64.decodeBuffer(encodedString);
> + }
> }
This should be package-private, there's no reason to expose this as part
of the class's interface.
Unit test:
> diff --git a/tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java
> b/tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java
> --- a/tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java
> +++ b/tests/netx/unit/net/sourceforge/jnlp/JNLPFileTest.java
> @@ -37,6 +37,10 @@
>
> package net.sourceforge.jnlp;
>
> +import java.io.ByteArrayInputStream;
> +import java.io.InputStream;
> +import java.net.MalformedURLException;
> +import java.net.URL;
> import java.util.Locale;
>
> import net.sourceforge.jnlp.JNLPFile.Match;
> @@ -103,4 +107,45 @@
> Assert.assertFalse("Locales list should not match generalized
> case but did.",
> file.localeMatches(jvmLocale, mismatchAvailable,
> Match.GENERALIZED));
> }
> +
> + @Test
> + public void testCodebaseConstructorWithInputstreamAndCodebase()
> throws Exception {
> + String jnlpContext = "<?xml version=\"1.0\"?>\n" +
> + "<jnlp spec=\"1.5+\"\n" +
> + "href=\"EmbeddedJnlpFile.jnlp\"\n" +
> + "codebase=\"http://icedtea.claspath.org\"\n" +
> + ">\n" +
> + "" +
> + "<information>\n" +
> + "<title>Sample Test</title>\n" +
> + "<vendor>RedHat</vendor>\n" +
> + "<offline-allowed/>\n" +
> + "</information>\n" +
> + "\n" +
> + "<resources>\n" +
> + "<j2se version='1.6+' />\n" +
> + "<jar href='EmbeddedJnlpJarOne.jar' main='true'/>\n" +
> + "<jar href='EmbeddedJnlpJarTwo.jar' main='true'/>\n" +
> + "</resources>\n" +
> + "\n" +
> + "<applet-desc\n" +
> + "documentBase=\".\"\n" +
> + "name=\"redhat.embeddedjnlp\"\n" +
> + "main-class=\"redhat.embeddedjnlp\"\n" +
> + "width=\"0\"\n" +
> + "height=\"0\"\n" +
> + "/>\n" +
> + "</jnlp>";
> +
> + URL codeBase = new URL("http://www.redhat.com/");
> + ;
> + InputStream is = new
> ByteArrayInputStream(jnlpContext.getBytes());
> +
> + JNLPFile jnlpFile = new JNLPFile(is, codeBase, false);
> +
> + Assert.assertEquals("http://icedtea.claspath.org/",
> jnlpFile.getCodeBase().toExternalForm());
> + Assert.assertEquals("redhat.embeddedjnlp",
> jnlpFile.getApplet().getMainClass());
> + Assert.assertEquals("Sample Test", jnlpFile.getTitle());
> + Assert.assertEquals(2, jnlpFile.getResources().getJARs().length);
> + }
> }
> diff --git a/tests/netx/unit/net/sourceforge/jnlp/ParserTest.java
> b/tests/netx/unit/net/sourceforge/jnlp/ParserTest.java
> --- a/tests/netx/unit/net/sourceforge/jnlp/ParserTest.java
> +++ b/tests/netx/unit/net/sourceforge/jnlp/ParserTest.java
> @@ -38,6 +38,7 @@
> package net.sourceforge.jnlp;
>
> import java.io.ByteArrayInputStream;
> +import java.net.URL;
> import java.util.ArrayList;
> import java.util.List;
> import java.util.Locale;
> @@ -1355,4 +1356,60 @@
>
> parser.checkForInformation();
> }
> +
> + @Test
> + public void testOverwrittenCodebaseWithValidJnlpCodebase() throws
> Exception {
> + String data = "<?xml version=\"1.0\"?>\n" +
> + "<jnlp spec=\"1.5+\"\n" +
> + "href=\"EmbeddedJnlpFile.jnlp\"\n" +
> + "codebase=\"http://www.redhat.com/\"\n" +
> + ">\n" +
> + "</jnlp>";
> +
> + Node root = Parser.getRootNode(new
> ByteArrayInputStream(data.getBytes()));
> + Assert.assertEquals("Root name is not jnlp", "jnlp",
> root.getNodeName());
> + URL overwrittenCodebase = new
> URL("http://icedtea.classpath.org");
> +
> + MockJNLPFile file = new MockJNLPFile(LANG_LOCALE);
> + Parser parser = new Parser(file, null, root, false, false,
> overwrittenCodebase);
> +
> + Assert.assertEquals("http://www.redhat.com/",
> parser.getCodeBase().toExternalForm());
> + }
> +
> + @Test
> + public void testOverwrittenCodebaseWithInvalidJnlpCodebase()
> throws Exception {
> + String data = "<?xml version=\"1.0\"?>\n" +
> + "<jnlp spec=\"1.5+\"\n" +
> + "href=\"EmbeddedJnlpFile.jnlp\"\n" +
> + "codebase=\"this codebase is incorrect\"\n" +
> + ">\n" +
> + "</jnlp>";
> +
> + Node root = Parser.getRootNode(new
> ByteArrayInputStream(data.getBytes()));
> + Assert.assertEquals("Root name is not jnlp", "jnlp",
> root.getNodeName());
> + URL overwrittenCodebase = new
> URL("http://icedtea.classpath.org");
> +
> + MockJNLPFile file = new MockJNLPFile(LANG_LOCALE);
> + Parser parser = new Parser(file, null, root, false, false,
> overwrittenCodebase);
> +
> + Assert.assertEquals(overwrittenCodebase.toExternalForm(),
> parser.getCodeBase().toExternalForm());
> + }
> +
> + @Test
> + public void testOverwrittenCodebaseWithNoJnlpCodebase() throws
> Exception {
> + String data = "<?xml version=\"1.0\"?>\n" +
> + "<jnlp spec=\"1.5+\"\n" +
> + "href=\"EmbeddedJnlpFile.jnlp\"\n" +
> + ">\n" +
> + "</jnlp>";
> +
> + Node root = Parser.getRootNode(new
> ByteArrayInputStream(data.getBytes()));
> + Assert.assertEquals("Root name is not jnlp", "jnlp",
> root.getNodeName());
> + URL overwrittenCodebase = new
> URL("http://icedtea.classpath.org");
> +
> + MockJNLPFile file = new MockJNLPFile(LANG_LOCALE);
> + Parser parser = new Parser(file, null, root, false, false,
> overwrittenCodebase);
> +
> + Assert.assertEquals(overwrittenCodebase.toExternalForm(),
> parser.getCodeBase().toExternalForm());
> + }
> }
> diff --git
> a/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java
> b/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java
> --- a/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java
> +++ b/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java
> @@ -27,13 +27,20 @@
> import java.io.IOException;
> import java.net.MalformedURLException;
> import java.net.URL;
> +import java.util.ArrayList;
> import java.util.HashMap;
> import java.util.Hashtable;
> +import java.util.List;
> +import junit.framework.Assert;
>
> import net.sourceforge.jnlp.cache.UpdatePolicy;
>
> import org.junit.Test;
>
> +import sun.misc.BASE64Encoder;
> +
> +import com.sun.org.apache.bcel.internal.generic.INSTANCEOF;
> +
> public class PluginBridgeTest {
> private class MockJNLPCreator extends JNLPCreator {
>
> @@ -96,4 +103,206 @@
> mockCreator.getJNLPHref().toExternalForm());
> }
>
> + @Test
> + public void testDecodingJNLPFile() throws Exception {
> + String actualFile = "<?xml version=\"1.0\"?>\n" +
> + "<jnlp spec=\"1.5+\"\n" +
> + "href=\"EmbeddedJnlpFile.jnlp\"\n" +
> + "codebase=\"http://www.redhat.com\"\n" +
> + ">\n" +
> + "" +
> + "<information>\n" +
> + "<title>Sample Test</title>\n" +
> + "<vendor>RedHat</vendor>\n" +
> + "<offline-allowed/>\n" +
> + "</information>\n" +
> + "\n" +
> + "<resources>\n" +
> + "<j2se version='1.6+' />\n" +
> + "<jar href='EmbeddedJnlpJarOne.jar' main='true'/>\n" +
> + "<jar href='EmbeddedJnlpJarTwo.jar' main='true'/>\n" +
> + "</resources>\n" +
> + "\n" +
> + "<applet-desc\n" +
> + "documentBase=\".\"\n" +
> + "name=\"redhat.embeddedjnlp\"\n" +
> + "main-class=\"redhat.embeddedjnlp\"\n" +
> + "width=\"0\"\n" +
> + "height=\"0\"\n" +
> + "/>\n" +
> + "</jnlp>";
> +
> + BASE64Encoder encoder = new BASE64Encoder();
> + String encodedFile = encoder.encodeBuffer(actualFile.getBytes());
> +
> + byte[] decodedBytes =
> PluginBridge.decodeBase64String(encodedFile);
> + String decodedString = new String(decodedBytes);
> + Assert.assertEquals(actualFile, decodedString);
This is a rather long test-string for whats already a very well tested
method (the underlying implementation is well-tested, that is.) If you
are going to test it, I would use a simple short message. The test will
be easier to understand as a result (it has nothing to do with JNLP
files). Also the test name is inaccurate, it is merely testing
PluginBridge.decodeBase64String.
> + }
> +
> + @Test
> + public void testEmbeddedJnlpWithValidCodebase() throws Exception {
> + URL codeBase = new URL("http://icedtea.classpath.org");
> + String relativeLocation = "/EmbeddedJnlpFile.jnlp";
> +
> + //Codebase within jnlp file is VALID
> + /**
> + <?xml version="1.0"?>
> + <jnlp spec="1.5+"
> + href="EmbeddedJnlpFile.jnlp"
> + codebase="http://www.redhat.com"
> + >
> +
> + <information>
> + <title>Sample Test</title>
> + <vendor>RedHat</vendor>
> + <offline-allowed/>
> + </information>
> +
> + <resources>
> + <j2se version='1.6+' />
> + <jar href='EmbeddedJnlpJarOne.jar' main='true' />
> + <jar href='EmbeddedJnlpJarTwo.jar' main='true' />
> + </resources>
> +
> + <applet-desc
> + documentBase="."
> + name="redhat.embeddedjnlp"
> + main-class="redhat.embeddedjnlp"
> + width="0"
> + height="0"
> + />
> + </jnlp>
> + **/
> +
> + String jnlpFileEncoded =
> "ICAgICAgICA8P3htbCB2ZXJzaW9uPSIxLjAiPz4NCiAgICAgICAgICAgIDxqbmxwIHNwZWM9IjEu"
> +
> +
> "NSsiIA0KICAgICAgICAgICAgICBocmVmPSJFbWJlZGRlZEpubHBGaWxlLmpubHAiIA0KICAgICAg"
> +
> +
> "ICAgICAgICBjb2RlYmFzZT0iaHR0cDovL3d3dy5yZWRoYXQuY29tIiAgICANCiAgICAgICAgICAg"
> +
> +
> "ID4NCg0KICAgICAgICAgICAgPGluZm9ybWF0aW9uPg0KICAgICAgICAgICAgICAgIDx0aXRsZT5T"
> +
> +
> "YW1wbGUgVGVzdDwvdGl0bGU+DQogICAgICAgICAgICAgICAgPHZlbmRvcj5SZWRIYXQ8L3ZlbmRv"
> +
> +
> "cj4NCiAgICAgICAgICAgICAgICA8b2ZmbGluZS1hbGxvd2VkLz4NCiAgICAgICAgICAgIDwvaW5m"
> +
> +
> "b3JtYXRpb24+DQoNCiAgICAgICAgICAgIDxyZXNvdXJjZXM+DQogICAgICAgICAgICAgICAgPGoy"
> +
> +
> "c2UgdmVyc2lvbj0nMS42KycgLz4NCiAgICAgICAgICAgICAgICA8amFyIGhyZWY9J0VtYmVkZGVk"
> +
> +
> "Sm5scEphck9uZS5qYXInIG1haW49J3RydWUnIC8+DQogICAgICAgICAgICAgICAgPGphciBocmVm"
> +
> +
> "PSdFbWJlZGRlZEpubHBKYXJUd28uamFyJyBtYWluPSd0cnVlJyAvPg0KICAgICAgICAgICAgPC9y"
> +
> +
> "ZXNvdXJjZXM+DQoNCiAgICAgICAgICAgIDxhcHBsZXQtZGVzYw0KICAgICAgICAgICAgICAgIGRv"
> +
> +
> "Y3VtZW50QmFzZT0iLiINCiAgICAgICAgICAgICAgICBuYW1lPSJyZWRoYXQuZW1iZWRkZWRqbmxw"
> +
> +
> "Ig0KICAgICAgICAgICAgICAgIG1haW4tY2xhc3M9InJlZGhhdC5lbWJlZGRlZGpubHAiDQogICAg"
> +
> +
> "ICAgICAgICAgICAgd2lkdGg9IjAiDQogICAgICAgICAgICAgICAgaGVpZ2h0PSIwIg0KICAgICAg"
> +
> + "ICAgICAgLz4NCiAgICAgICAgICAgIDwvam5scD4=";
> +
> + MockJNLPCreator mockCreator = new MockJNLPCreator();
> + Hashtable<String, String> atts = new Hashtable<String, String>();
> + atts.put("jnlp_href", relativeLocation);
> + atts.put("jnlp_embedded", jnlpFileEncoded);
> +
> + String jnlpCodebase = "http://www.redhat.com";
> + PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0,
> 0, atts, "", mockCreator);
> + JARDesc[] jars = pb.getResources().getJARs();
> +
> + //Check if there are two jars cached
> + Assert.assertTrue(jars.length == 2);
> +
> + //Resource can be in any order
> + List<String> resourceLocations = new ArrayList<String>();
> + resourceLocations.add(jars[0].getLocation().toExternalForm());
> + resourceLocations.add(jars[1].getLocation().toExternalForm());
> +
> + //Check URLs of jars
> + Assert.assertTrue(resourceLocations.contains(jnlpCodebase +
> "/EmbeddedJnlpJarOne.jar"));
> + Assert.assertTrue((resourceLocations.contains(jnlpCodebase +
> "/EmbeddedJnlpJarTwo.jar")));
> + }
> +
> + @Test
> + public void testEmbeddedJnlpWithInvalidCodebase() throws Exception {
> + URL overwrittenCodebase = new
> URL("http://icedtea.classpath.org");
> + String relativeLocation = "/EmbeddedJnlpFile.jnlp";
> +
> + //Codebase within jnlp file is INVALID
> + /**
> + <?xml version="1.0"?>
> + <jnlp spec="1.5+"
> + href="EmbeddedJnlpFile.jnlp"
> + codebase="invalidPath"
> + >
> +
> + <information>
> + <title>Sample Test</title>
> + <vendor>RedHat</vendor>
> + <offline-allowed/>
> + </information>
> +
> + <resources>
> + <j2se version='1.6+' />
> + <jar href='EmbeddedJnlpJarOne.jar' main='true' />
> + <jar href='EmbeddedJnlpJarTwo.jar' main='true' />
> + </resources>
> +
> + <applet-desc
> + documentBase="."
> + name="redhat.embeddedjnlp"
> + main-class="redhat.embeddedjnlp"
> + width="0"
> + height="0"
> + />
> + </jnlp>
> + **/
> +
> + String jnlpFileEncoded =
> "ICAgICAgICA8P3htbCB2ZXJzaW9uPSIxLjAiPz4NCiAgICAgICAgICAgIDxqbmxwIHNwZWM9IjEu"
> +
> +
> "NSsiIA0KICAgICAgICAgICAgICBocmVmPSJFbWJlZGRlZEpubHBGaWxlLmpubHAiIA0KICAgICAg"
> +
> +
> "ICAgICAgICBjb2RlYmFzZT0iaW52YWxpZFBhdGgiICAgIA0KICAgICAgICAgICAgPg0KDQogICAg"
> +
> +
> "ICAgICAgICA8aW5mb3JtYXRpb24+DQogICAgICAgICAgICAgICAgPHRpdGxlPlNhbXBsZSBUZXN0"
> +
> +
> "PC90aXRsZT4NCiAgICAgICAgICAgICAgICA8dmVuZG9yPlJlZEhhdDwvdmVuZG9yPg0KICAgICAg"
> +
> +
> "ICAgICAgICAgIDxvZmZsaW5lLWFsbG93ZWQvPg0KICAgICAgICAgICAgPC9pbmZvcm1hdGlvbj4N"
> +
> +
> "Cg0KICAgICAgICAgICAgPHJlc291cmNlcz4NCiAgICAgICAgICAgICAgICA8ajJzZSB2ZXJzaW9u"
> +
> +
> "PScxLjYrJyAvPg0KICAgICAgICAgICAgICAgIDxqYXIgaHJlZj0nRW1iZWRkZWRKbmxwSmFyT25l"
> +
> +
> "LmphcicgbWFpbj0ndHJ1ZScgLz4NCiAgICAgICAgICAgICAgICA8amFyIGhyZWY9J0VtYmVkZGVk"
> +
> +
> "Sm5scEphclR3by5qYXInIG1haW49J3RydWUnIC8+DQogICAgICAgICAgICA8L3Jlc291cmNlcz4N"
> +
> +
> "Cg0KICAgICAgICAgICAgPGFwcGxldC1kZXNjDQogICAgICAgICAgICAgICAgZG9jdW1lbnRCYXNl"
> +
> +
> "PSIuIg0KICAgICAgICAgICAgICAgIG5hbWU9InJlZGhhdC5lbWJlZGRlZGpubHAiDQogICAgICAg"
> +
> +
> "ICAgICAgICAgbWFpbi1jbGFzcz0icmVkaGF0LmVtYmVkZGVkam5scCINCiAgICAgICAgICAgICAg"
> +
> +
> "ICB3aWR0aD0iMCINCiAgICAgICAgICAgICAgICBoZWlnaHQ9IjAiDQogICAgICAgICAgICAvPg0K"
> +
> + "ICAgICAgICAgICAgPC9qbmxwPg==";
> +
> + MockJNLPCreator mockCreator = new MockJNLPCreator();
> + Hashtable<String, String> atts = new Hashtable<String, String>();
> + atts.put("jnlp_href", relativeLocation);
> + atts.put("jnlp_embedded", jnlpFileEncoded);
> +
> + PluginBridge pb = new PluginBridge(overwrittenCodebase, null,
> "", "", 0, 0, atts, "", mockCreator);
> + JARDesc[] jars = pb.getResources().getJARs();
> +
> + //Check if there are two jars cached
> + Assert.assertTrue(jars.length == 2);
> +
> + //Resource can be in any order
> + List<String> resourceLocations = new ArrayList<String>();
> + resourceLocations.add(jars[0].getLocation().toExternalForm());
> + resourceLocations.add(jars[1].getLocation().toExternalForm());
> +
> + //Check URLs of jars
> + Assert.assertTrue(resourceLocations.contains(overwrittenCodebase +
> "/EmbeddedJnlpJarOne.jar"));
> + Assert.assertTrue((resourceLocations.contains(overwrittenCodebase +
> "/EmbeddedJnlpJarTwo.jar")));
> + }
> +
> + @Test
> + public void testInvalidEmbeddedJnlp() throws Exception {
> + URL overwrittenCodebase = new
> URL("http://icedtea.classpath.org");
> + String relativeLocation = "/EmbeddedJnlpFile.jnlp";
> +
> + //Embedded jnlp is invalid
> + String jnlpFileEncoded = "thisContextIsInvalid";
> +
> + MockJNLPCreator mockCreator = new MockJNLPCreator();
> + Hashtable<String, String> atts = new Hashtable<String, String>();
> + atts.put("jnlp_href", relativeLocation);
> + atts.put("jnlp_embedded", jnlpFileEncoded);
> +
> + try {
> + new PluginBridge(overwrittenCodebase, null, "", "", 0, 0,
> atts, "", mockCreator);
> + } catch (Exception e) {
> + return;
> + }
> + Assert.fail("PluginBridge was successfully created with an
> invalid embedded jnlp value");
> + }
> }
> \ No newline at end of file
Thanks for including unit tests & reproducers. It is almost push-ready
other than my few nits.
Good patch overall, the implementation is rather elegant.
Cheers,
- Adam
More information about the distro-pkg-dev
mailing list