aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Domurad <adomurad@redhat.com>2012-12-04 10:43:59 -0500
committerAdam Domurad <adomurad@redhat.com>2012-12-04 10:43:59 -0500
commit1f595aba1e38b1a0113f45492288e22d3fa90799 (patch)
tree422a8d29652e3084915801fdc960c1c3099ae2a4
parent7aff0a246448bef22d89859b07fef92c128e14e5 (diff)
Remove redundant HTML-tag scanner from ITW. Do not reconstruct tags.
-rw-r--r--ChangeLog35
-rw-r--r--Makefile.am4
-rw-r--r--netx/net/sourceforge/jnlp/NetxPanel.java57
-rw-r--r--netx/net/sourceforge/jnlp/PluginBridge.java64
-rw-r--r--netx/net/sourceforge/jnlp/PluginParameterException.java43
-rw-r--r--netx/net/sourceforge/jnlp/PluginParameters.java238
-rw-r--r--netx/net/sourceforge/jnlp/resources/Messages.properties1
-rw-r--r--netx/net/sourceforge/jnlp/resources/Messages_cs_CZ.properties1
-rw-r--r--plugin/icedteanp/IcedTeaNPPlugin.cc221
-rw-r--r--plugin/icedteanp/IcedTeaNPPlugin.h4
-rw-r--r--plugin/icedteanp/java/sun/applet/PluginAppletViewer.java534
-rw-r--r--plugin/icedteanp/java/sun/applet/PluginParameterParser.java90
-rw-r--r--tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc2
-rw-r--r--tests/cpp-unit-tests/PluginParametersTest.cc93
-rw-r--r--tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java53
-rw-r--r--tests/netx/unit/net/sourceforge/jnlp/PluginParametersTest.java114
-rw-r--r--tests/netx/unit/sun/applet/PluginParameterParserTest.java73
17 files changed, 842 insertions, 785 deletions
diff --git a/ChangeLog b/ChangeLog
index 68e5269..8de285c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2012-12-04 Adam Domurad <adomurad@redhat.com>
+
+ Remove the applet/embed/object tag parser from ITW. Send the applet
+ parameters directly from the C++.
+ * Makefile.am: Allow unit-testing for classes in plugin.jar.
+ * netx/net/sourceforge/jnlp/NetxPanel.java: Use PluginParameters for
+ attribute lookup
+ * netx/net/sourceforge/jnlp/PluginBridge.java: Use PluginParameters
+ for attribute lookup
+ * netx/net/sourceforge/jnlp/resources/Messages.properties: Add message
+ for missing code/object attributes.
+ * netx/net/sourceforge/jnlp/resources/Messages_cs_CZ.properties: Same.
+ * plugin/icedteanp/IcedTeaNPPlugin.cc: Send escaped parameter
+ name/values instead of applet tag. Remove some dead code.
+ * plugin/icedteanp/IcedTeaNPPlugin.h: Rename applet_tag ->
+ parameters_string.
+ * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java: Extract
+ parsing code into its own class.
+ * tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc: Use CHECK_EQUALS
+ instead of CHECK.
+ * tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java: Update
+ unit tests due to constructor changes.
+ * netx/net/sourceforge/jnlp/PluginParameterException.java: New, thrown
+ when code/object attributes are missing.
+ * netx/net/sourceforge/jnlp/PluginParameters.java: New, Hashtable
+ wrapper that handles plugin attribute/parameter lookups.
+ * plugin/icedteanp/java/sun/applet/PluginParameterParser.java: New,
+ creates PluginParameters from escaped name/values.
+ * tests/cpp-unit-tests/PluginParametersTest.cc: New, C++ Unit tests for
+ plugin parameter related functions
+ * tests/netx/unit/net/sourceforge/jnlp/PluginParametersTest.java: New,
+ unit tests for PluginParameters class.
+ * tests/netx/unit/sun/applet/PluginParameterParserTest.java: New, unit
+ tests for PluginParameterParser class.
+
2012-11-03 Jiri Vanek <jvanek@redhat.com>
Fixed logging bottleneck
diff --git a/Makefile.am b/Makefile.am
index d66f278..3a2a1b0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -969,7 +969,7 @@ stamps/netx-unit-tests-compile.stamp: stamps/netx.stamp \
mkdir -p $(NETX_UNIT_TEST_DIR) && \
$(BOOT_DIR)/bin/javac $(IT_JAVACFLAGS) \
-d $(NETX_UNIT_TEST_DIR) \
- -classpath $(JUNIT_JAR):$(NETX_DIR)/lib/classes.jar:$(TEST_EXTENSIONS_DIR) \
+ -classpath $(JUNIT_JAR):$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar:$(NETX_DIR)/lib/classes.jar:$(TEST_EXTENSIONS_DIR) \
@netx-unit-tests-source-files.txt && \
mkdir -p stamps && \
touch $@
@@ -999,7 +999,7 @@ stamps/run-netx-unit-tests.stamp: stamps/netx-unit-tests-compile.stamp $(JUNIT_R
done ; \
cd $(NETX_UNIT_TEST_DIR) ; \
class_names=`cat $(UNIT_CLASS_NAMES)` ; \
- CLASSPATH=$(NETX_DIR)/lib/classes.jar:$(JUNIT_JAR):$(JUNIT_RUNNER_JAR):$(TEST_EXTENSIONS_DIR):. \
+ CLASSPATH=$(NETX_DIR)/lib/classes.jar:$(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar:$(JUNIT_JAR):$(JUNIT_RUNNER_JAR):$(TEST_EXTENSIONS_DIR):. \
$(BOOT_DIR)/bin/java -Xbootclasspath:$(RUNTIME) CommandLine $$class_names
if WITH_XSLTPROC
$(XSLTPROC) --stringparam logs logs_unit.html $(TESTS_SRCDIR)/$(REPORT_STYLES_DIRNAME)/jreport.xsl $(NETX_UNIT_TEST_DIR)/tests-output.xml > $(TESTS_DIR)/index_unit.html
diff --git a/netx/net/sourceforge/jnlp/NetxPanel.java b/netx/net/sourceforge/jnlp/NetxPanel.java
index ce20d5c..1afa416 100644
--- a/netx/net/sourceforge/jnlp/NetxPanel.java
+++ b/netx/net/sourceforge/jnlp/NetxPanel.java
@@ -27,7 +27,6 @@ import net.sourceforge.jnlp.runtime.JNLPRuntime;
import java.net.URL;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -45,12 +44,12 @@ import sun.awt.SunToolkit;
* @author Francis Kung <fkung@redhat.com>
*/
public class NetxPanel extends AppletViewerPanel implements SplashController {
+ private final PluginParameters parameters;
private PluginBridge bridge = null;
private boolean exitOnFailure = true;
private AppletInstance appInst = null;
private SplashController splashController;
private boolean appletAlive;
- private final String uKey;
// We use this so that we can create exactly one thread group
// for all panels with the same uKey.
@@ -68,51 +67,24 @@ public class NetxPanel extends AppletViewerPanel implements SplashController {
private static final ConcurrentMap<String, Boolean> appContextCreated =
new ConcurrentHashMap<String, Boolean>();
- public NetxPanel(URL documentURL, Hashtable<String, String> atts) {
- super(documentURL, atts);
+ public NetxPanel(URL documentURL, PluginParameters params) {
+ super(documentURL, params.getUnderlyingHashtable());
- /* According to http://download.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/applet-compatibility.html,
- * classloaders are shared iff these properties match:
- * codebase, cache_archive, java_archive, archive
- *
- * To achieve this, we create the uniquekey based on those 4 values,
- * always in the same order. The initial "<NAME>=" parts ensure a
- * bad tag cannot trick the loader into getting shared with another.
- */
-
- // Firefox sometimes skips the codebase if it is default -- ".",
- // so set it that way if absent
- String codebaseAttr = atts.get("codebase") != null ?
- atts.get("codebase") : ".";
-
- String cache_archiveAttr = atts.get("cache_archive") != null ?
- atts.get("cache_archive") : "";
-
- String java_archiveAttr = atts.get("java_archive") != null ?
- atts.get("java_archive") : "";
+ this.parameters = params;
- String archiveAttr = atts.get("archive") != null ?
- atts.get("archive") : "";
-
- this.uKey = "codebase=" + codebaseAttr +
- "cache_archive=" + cache_archiveAttr +
- "java_archive=" + java_archiveAttr +
- "archive=" + archiveAttr;
-
- // when this was being done (incorrectly) in Launcher, the call was
- // new AppThreadGroup(mainGroup, file.getTitle());
+ String uniqueKey = params.getUniqueKey();
synchronized(TGMapMutex) {
- if (!uKeyToTG.containsKey(this.uKey)) {
+ if (!uKeyToTG.containsKey(uniqueKey)) {
ThreadGroup tg = new ThreadGroup(Launcher.mainGroup, this.documentURL.toString());
- uKeyToTG.put(this.uKey, tg);
+ uKeyToTG.put(uniqueKey, tg);
}
}
}
// overloaded constructor, called when initialized via plugin
- public NetxPanel(URL documentURL, Hashtable<String, String> atts,
+ public NetxPanel(URL documentURL, PluginParameters params,
boolean exitOnFailure) {
- this(documentURL, atts);
+ this(documentURL, params);
this.exitOnFailure = exitOnFailure;
this.appletAlive = true;
}
@@ -129,6 +101,7 @@ public class NetxPanel extends AppletViewerPanel implements SplashController {
//Overriding to use Netx classloader. You might need to relax visibility
//in sun.applet.AppletPanel for runLoader().
+ @Override
protected void runLoader() {
try {
@@ -138,7 +111,7 @@ public class NetxPanel extends AppletViewerPanel implements SplashController {
getCode(),
getWidth(),
getHeight(),
- atts, uKey);
+ parameters);
doInit = true;
dispatchAppletEvent(APPLET_LOADING, null);
@@ -188,6 +161,7 @@ public class NetxPanel extends AppletViewerPanel implements SplashController {
* the applet
*/
// Reminder: Relax visibility in sun.applet.AppletPanel
+ @Override
protected synchronized void createAppletThread() {
// initialize JNLPRuntime in the main threadgroup
synchronized (JNLPRuntime.initMutex) {
@@ -208,8 +182,7 @@ public class NetxPanel extends AppletViewerPanel implements SplashController {
}
public void updateSizeInAtts(int height, int width) {
- this.atts.put("height", Integer.toString(height));
- this.atts.put("width", Integer.toString(width));
+ parameters.updateSize(width, height);
}
public ClassLoader getAppletClassLoader() {
@@ -222,7 +195,7 @@ public class NetxPanel extends AppletViewerPanel implements SplashController {
public ThreadGroup getThreadGroup() {
synchronized(TGMapMutex) {
- return uKeyToTG.get(uKey);
+ return uKeyToTG.get(parameters.getUniqueKey());
}
}
@@ -232,7 +205,7 @@ public class NetxPanel extends AppletViewerPanel implements SplashController {
}
// only create a new context if one hasn't already been created for the
// applets with this unique key.
- if (null == appContextCreated.putIfAbsent(uKey, Boolean.TRUE)) {
+ if (null == appContextCreated.putIfAbsent(parameters.getUniqueKey(), Boolean.TRUE)) {
SunToolkit.createNewAppContext();
}
}
diff --git a/netx/net/sourceforge/jnlp/PluginBridge.java b/netx/net/sourceforge/jnlp/PluginBridge.java
index 37b72e6..1e34c49 100644
--- a/netx/net/sourceforge/jnlp/PluginBridge.java
+++ b/netx/net/sourceforge/jnlp/PluginBridge.java
@@ -45,26 +45,23 @@ import net.sourceforge.jnlp.runtime.JNLPRuntime;
*/
public class PluginBridge extends JNLPFile {
- private String name;
+ private PluginParameters params;
private Set<String> jars = new HashSet<String>();
//Folders can be added to the code-base through the archive tag
private List<String> codeBaseFolders = new ArrayList<String>();
private String[] cacheJars = new String[0];
private String[] cacheExJars = new String[0];
- private Map<String, String> atts;
private boolean usePack;
private boolean useVersion;
- private boolean codeBaseLookup;
private boolean useJNLPHref;
/**
* Creates a new PluginBridge using a default JNLPCreator.
*/
public PluginBridge(URL codebase, URL documentBase, String jar, String main,
- int width, int height, Map<String, String> atts,
- String uKey)
+ int width, int height, PluginParameters params)
throws Exception {
- this(codebase, documentBase, jar, main, width, height, atts, uKey, new JNLPCreator());
+ this(codebase, documentBase, jar, main, width, height, params, new JNLPCreator());
}
/**
@@ -86,25 +83,24 @@ public class PluginBridge extends JNLPFile {
}
public PluginBridge(URL codebase, URL documentBase, String archive, String main,
- int width, int height, Map<String, String> atts,
- String uKey, JNLPCreator jnlpCreator)
+ int width, int height, PluginParameters params, JNLPCreator jnlpCreator)
throws Exception {
specVersion = new Version("1.0");
fileVersion = new Version("1.1");
this.codeBase = codebase;
this.sourceLocation = documentBase;
- this.atts = atts;
+ this.params = params;
- if (atts.containsKey("jnlp_href")) {
+ if (params.getJNLPHref() != null) {
useJNLPHref = true;
try {
// 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"));
+ URL jnlp = new URL(codeBase, params.getJNLPHref());
JNLPFile jnlpFile = null;
- if (atts.containsKey("jnlp_embedded")) {
- InputStream jnlpInputStream = new ByteArrayInputStream(decodeBase64String(atts.get("jnlp_embedded")));
+ if (params.getJNLPEmbedded() != null) {
+ InputStream jnlpInputStream = new ByteArrayInputStream(decodeBase64String(params.getJNLPEmbedded()));
jnlpFile = new JNLPFile(jnlpInputStream, codeBase, false);
} else {
jnlpFile = jnlpCreator.create(jnlp, null, false, JNLPRuntime.getDefaultUpdatePolicy(), codeBase);
@@ -118,7 +114,7 @@ public class PluginBridge extends JNLPFile {
// Change the parameter name to lowercase to follow conventions.
for (Map.Entry<String, String> entry : jnlpParams.entrySet()) {
- this.atts.put(entry.getKey().toLowerCase(), entry.getValue());
+ this.params.put(entry.getKey().toLowerCase(), entry.getValue());
}
JARDesc[] jarDescs = jnlpFile.getResources().getJARs();
for (JARDesc jarDesc : jarDescs) {
@@ -128,7 +124,7 @@ public class PluginBridge extends JNLPFile {
} catch (MalformedURLException e) {
// Don't fail because we cannot get the jnlp file. Parameters are optional not required.
// it is the site developer who should ensure that file exist.
- System.err.println("Unable to get JNLP file at: " + atts.get("jnlp_href")
+ System.err.println("Unable to get JNLP file at: " + params.getJNLPHref()
+ " with context of URL as: " + codeBase.toExternalForm());
}
} else {
@@ -138,14 +134,14 @@ public class PluginBridge extends JNLPFile {
}
// also, see if cache_archive is specified
- String cacheArchive = atts.get("cache_archive");
- if (cacheArchive != null && cacheArchive.length() > 0) {
+ String cacheArchive = params.getCacheArchive();
+ if (!cacheArchive.isEmpty()) {
String[] versions = new String[0];
// are there accompanying versions?
- String cacheVersion = atts.get("cache_version");
- if (cacheVersion != null) {
+ String cacheVersion = params.getCacheVersion();
+ if (!cacheVersion.isEmpty()) {
versions = cacheVersion.split(",");
}
@@ -162,8 +158,8 @@ public class PluginBridge extends JNLPFile {
}
}
- String cacheArchiveEx = atts.get("cache_archive_ex");
- if (cacheArchiveEx != null && cacheArchiveEx.length() > 0) {
+ String cacheArchiveEx = params.getCacheArchiveEx();
+ if (!cacheArchiveEx.isEmpty()) {
cacheExJars = cacheArchiveEx.split(",");
}
@@ -178,19 +174,13 @@ public class PluginBridge extends JNLPFile {
}
}
- name = atts.get("name");
- if (name == null)
- name = "Applet";
- else
- name = name + " applet";
-
if (main.endsWith(".class"))
main = main.substring(0, main.length() - 6);
// the class name should be of the form foo.bar.Baz not foo/bar/Baz
String mainClass = main.replace('/', '.');
- launchType = new AppletDesc(name, mainClass, documentBase, width,
- height, atts);
+ launchType = new AppletDesc(params.getAppletTitle(), mainClass, documentBase, width,
+ height, params.getUnmodifiableMap());
if (main.endsWith(".class")) //single class file only
security = new SecurityDesc(this, SecurityDesc.SANDBOX_PERMISSIONS,
@@ -198,11 +188,11 @@ public class PluginBridge extends JNLPFile {
else
security = null;
- this.uniqueKey = uKey;
+ this.uniqueKey = params.getUniqueKey();
usePack = false;
useVersion = false;
- String jargs = atts.get("java_arguments");
- if (jargs != null) {
+ String jargs = params.getJavaArguments();
+ if (!jargs.isEmpty()) {
for (String s : jargs.split(" ")) {
String[] parts = s.trim().split("=");
if (parts.length == 2 && Boolean.valueOf(parts[1])) {
@@ -214,12 +204,10 @@ public class PluginBridge extends JNLPFile {
}
}
}
- String cbl = atts.get("codebase_lookup");
- codeBaseLookup = cbl == null || (Boolean.valueOf(cbl));
}
public boolean codeBaseLookup() {
- return codeBaseLookup;
+ return params.useCodebaseLookup();
}
public boolean useJNLPHref() {
@@ -235,7 +223,7 @@ public class PluginBridge extends JNLPFile {
}
public String getTitle() {
- return name;
+ return params.getAppletTitle();
}
public ResourcesDesc getResources(final Locale locale, final String os,
@@ -258,9 +246,7 @@ public class PluginBridge extends JNLPFile {
}
boolean cacheable = true;
-
- String cacheOption = atts.get("cache_option");
- if (cacheOption != null && cacheOption.equalsIgnoreCase("no"))
+ if (params.getCacheOption().equalsIgnoreCase("no"))
cacheable = false;
for (String cacheJar : cacheJars) {
diff --git a/netx/net/sourceforge/jnlp/PluginParameterException.java b/netx/net/sourceforge/jnlp/PluginParameterException.java
new file mode 100644
index 0000000..b1e1e9d
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/PluginParameterException.java
@@ -0,0 +1,43 @@
+/* Copyright (C) 2012 Red Hat
+
+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; either version 2, or (at your option)
+any later version.
+
+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;
+
+public class PluginParameterException extends RuntimeException {
+ public PluginParameterException(String detail) {
+ super(detail);
+ }
+}
diff --git a/netx/net/sourceforge/jnlp/PluginParameters.java b/netx/net/sourceforge/jnlp/PluginParameters.java
new file mode 100644
index 0000000..6f0152e
--- /dev/null
+++ b/netx/net/sourceforge/jnlp/PluginParameters.java
@@ -0,0 +1,238 @@
+/* PluginAppletAttributes -- Provides parsing for applet attributes
+ Copyright (C) 2012 Red Hat
+
+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; either version 2, or (at your option)
+any later version.
+
+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.Collections;
+import java.util.Hashtable;
+import java.util.Map;
+
+import static net.sourceforge.jnlp.runtime.Translator.R;
+
+/**
+ * Represents plugin applet parameters, backed by a Hashtable.
+ */
+
+public class PluginParameters {
+ private final Hashtable<String, String> parameters;
+
+ public PluginParameters(Map<String, String> params) {
+ this.parameters = createParameterTable(params);
+
+ if (this.parameters.get("code") == null
+ && this.parameters.get("object") == null) {
+ throw new PluginParameterException(R("BNoCodeOrObjectApplet"));
+ }
+ }
+
+ // Note, lower-case key expected
+ public String get(String key) {
+ return this.parameters.get(key);
+ }
+
+ public void put(String key, String value) {
+ parameters.put(key.toLowerCase(), value);
+ }
+
+ public Map<String, String> getUnmodifiableMap() {
+ return Collections.unmodifiableMap(parameters);
+ }
+
+ /**
+ * Used for compatibility with Hashtable-expecting classes.
+ *
+ * @return the underlying hashtable.
+ */
+ Hashtable<String, String> getUnderlyingHashtable() {
+ return parameters;
+ }
+
+ public String getDefaulted(String key, String defaultStr) {
+ String value = get(key);
+ return (value != null) ? value : defaultStr;
+ }
+
+ public String getAppletTitle() {
+ String name = get("name");
+ if (name == null) {
+ return "Applet";
+ } else {
+ return name + " applet";
+ }
+ }
+
+ public String getCodebase() {
+ return getDefaulted("codebase", ".");
+ }
+
+ public boolean useCodebaseLookup() {
+ return Boolean.valueOf(getDefaulted("codebase_lookup", "true"));
+ }
+
+ public String getArchive() {
+ return getDefaulted("archive", "");
+ }
+
+ public String getJavaArchive() {
+ return getDefaulted("java_archive", "");
+ }
+
+ public String getJavaArguments() {
+ return getDefaulted("java_arguments", "");
+ }
+
+ public String getCacheArchive() {
+ return getDefaulted("cache_archive", "");
+ }
+
+ public String getCacheArchiveEx() {
+ return getDefaulted("cache_archive_ex", "");
+ }
+
+ public String getCacheOption() {
+ return getDefaulted("cache_option", "");
+ }
+
+ public String getCacheVersion() {
+ return getDefaulted("cache_version", "");
+ }
+
+ public String getCode() {
+ return getDefaulted("code", "");
+ }
+
+ public String getJNLPHref() {
+ return get("jnlp_href");
+ }
+
+ public String getJNLPEmbedded() {
+ return get("jnlp_embedded");
+ }
+
+ public String getJarFiles() {
+ return getDefaulted("archive", "");
+ }
+
+ public int getWidth() {
+ String widthStr = getDefaulted("width", "0");
+ return Integer.valueOf(widthStr);
+ }
+
+ public int getHeight() {
+ String heightStr = getDefaulted("height", "0");
+ return Integer.valueOf(heightStr);
+ }
+
+ public void updateSize(int width, int height) {
+ parameters.put("width", Integer.toString(width));
+ parameters.put("height", Integer.toString(height));
+ }
+
+ public String getUniqueKey() {
+ /* According to http://download.oracle.com/javase/6/docs/technotes/guides/deployment/deployment-guide/applet-compatibility.html,
+ * classloaders are shared iff these properties match:
+ * codebase, cache_archive, java_archive, archive
+ *
+ * To achieve this, we create the uniquekey based on those 4 values,
+ * always in the same order. The initial "<NAME>=" parts ensure a
+ * bad tag cannot trick the loader into getting shared with another.
+ */
+ return "codebase=" + getCodebase() + "cache_archive=" + getCacheArchive() +
+ "java_archive=" + getJavaArchive() + "archive=" + getArchive();
+ }
+
+ /**
+ * Replace an attribute with its 'java_'-prefixed version.
+ * Note that java_* aliases override older names:
+ * http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-nav
+ */
+ static void ensureJavaPrefixTakesPrecedence(Map<String, String> params,
+ String attribute) {
+ String javaPrefixAttribute = params.get("java_" + attribute);
+ if (javaPrefixAttribute != null) {
+ params.put(attribute, javaPrefixAttribute);
+ }
+ }
+
+ /**
+ * Creates the underlying hash table with the proper overrides. Ensure all
+ * keys are lowercase consistently.
+ *
+ * @param params
+ * the properties, before parameter aliasing rules.
+ * @return the resulting parameter table
+ */
+ static Hashtable<String, String> createParameterTable(
+ Map<String, String> rawParams) {
+ Hashtable<String, String> params = new Hashtable<String, String>();
+
+ for (Map.Entry<String, String> entry : rawParams.entrySet()) {
+ String key = entry.getKey().toLowerCase();
+ String value = entry.getValue();
+ params.put(key, value);
+ }
+
+ String codeTag = params.get("code");
+ String classID = params.get("classid");
+
+ // If there is a classid and no code tag present, transform it to code tag
+ if (codeTag == null && classID != null && !classID.startsWith("clsid:")) {
+ codeTag = classID;
+ params.put("code", codeTag);
+ }
+
+ // remove java: from code tag
+ if (codeTag != null && codeTag.startsWith("java:")) {
+ codeTag = codeTag.substring("java:".length());
+ params.put("code", codeTag);
+ }
+
+ // java_* aliases override older names:
+ // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-nav
+ ensureJavaPrefixTakesPrecedence(params, "code");
+ ensureJavaPrefixTakesPrecedence(params, "codebase");
+ ensureJavaPrefixTakesPrecedence(params, "archive");
+ ensureJavaPrefixTakesPrecedence(params, "object");
+ ensureJavaPrefixTakesPrecedence(params, "type");
+
+ return params;
+ }
+
+ public String toString() {
+ return parameters.toString();
+ }
+} \ No newline at end of file
diff --git a/netx/net/sourceforge/jnlp/resources/Messages.properties b/netx/net/sourceforge/jnlp/resources/Messages.properties
index e74cf36..ed34397 100644
--- a/netx/net/sourceforge/jnlp/resources/Messages.properties
+++ b/netx/net/sourceforge/jnlp/resources/Messages.properties
@@ -141,6 +141,7 @@ BFileLoc=JNLP file location
BBadProp=Incorrect property format {0} (should be key=value)
BBadParam=Incorrect parameter format {0} (should be name=value)
BNoDir=Directory {0} does not exist.
+BNoCodeOrObjectApplet=Applet tag must specify a 'code' or 'object' attribute.
RNoResource=Missing Resource: {0}
RShutdown=This exception to prevent shutdown of JVM, but the process has been terminated.
RExitTaken=Exit class already set and caller is not exit class.
diff --git a/netx/net/sourceforge/jnlp/resources/Messages_cs_CZ.properties b/netx/net/sourceforge/jnlp/resources/Messages_cs_CZ.properties
index 3fcbfbb..9663e19 100644
--- a/netx/net/sourceforge/jnlp/resources/Messages_cs_CZ.properties
+++ b/netx/net/sourceforge/jnlp/resources/Messages_cs_CZ.properties
@@ -139,6 +139,7 @@ BFileLoc=Um\u00edst\u011bn\u00ed souboru JNLP
BBadProp=Neplatn\u00fd form\u00e1t vlastnosti {0} (platn\u00fd form\u00e1t: kl\u00ed\u010d=hodnota)
BBadParam=Neplatn\u00fd form\u00e1t parametru {0} (platn\u00fd form\u00e1t: n\u00e1zev=hodnota)
BNoDir=Adres\u00e1\u0159 {0} neexistuje.
+BNoCodeOrObjectApplet=Zna\u010dka applet mus\u00ed m\u00edt defnov\u00e1n k\u00f3d nebo objekt - atributy 'code' nebo 'object' chyb\u00ed.
RNoResource=Chyb\u011bj\u00edc\u00ed zdroj: {0}
RShutdown=Tato v\u00fdjimka zabra\u0148uje ukon\u010den\u00ed prost\u0159ed\u00ed JVM, av\u0161ak proces byl ukon\u010den.
RExitTaken=T\u0159\u00edda exit class m\u016f\u017ee b\u00fdt nastavena pouze jednou a pouze ta pak m\u016f\u017ee ukon\u010dit prost\u0159ed\u00ed JVM.
diff --git a/plugin/icedteanp/IcedTeaNPPlugin.cc b/plugin/icedteanp/IcedTeaNPPlugin.cc
index 302e791..19a04a2 100644
--- a/plugin/icedteanp/IcedTeaNPPlugin.cc
+++ b/plugin/icedteanp/IcedTeaNPPlugin.cc
@@ -229,8 +229,7 @@ static gboolean plugin_out_pipe_callback (GIOChannel* source,
GIOCondition condition,
gpointer plugin_data);
static NPError plugin_start_appletviewer (ITNPPluginData* data);
-static gchar* plugin_create_applet_tag (int16_t argc, char* argn[],
- char* argv[]);
+std::string plugin_parameters_string (int argc, char* argn[], char* argv[]);
static void plugin_stop_appletviewer ();
// Uninitialize ITNPPluginData structure
static void plugin_data_destroy (NPP instance);
@@ -347,7 +346,6 @@ ITNP_New (NPMIMEType pluginType, NPP instance, uint16_t mode,
gchar* documentbase = NULL;
gchar* read_message = NULL;
- gchar* applet_tag = NULL;
gchar* cookie_info = NULL;
NPObject* npPluginObj = NULL;
@@ -395,11 +393,10 @@ ITNP_New (NPMIMEType pluginType, NPP instance, uint16_t mode,
documentbase = plugin_get_documentbase (instance);
if (documentbase && argc != 0)
{
- // Send applet tag message to appletviewer.
- applet_tag = plugin_create_applet_tag (argc, argn, argv);
+ // Send parameters to appletviewer.
+ std::string params_string = plugin_parameters_string(argc, argn, argv);
- data->applet_tag = (gchar*) malloc(strlen(applet_tag)*sizeof(gchar) + strlen(documentbase)*sizeof(gchar) + 32);
- g_sprintf(data->applet_tag, "tag %s %s", documentbase, applet_tag);
+ data->parameters_string = g_strdup_printf("tag %s %s", documentbase, params_string.c_str());
data->is_applet_instance = true;
}
@@ -424,33 +421,7 @@ ITNP_New (NPMIMEType pluginType, NPP instance, uint16_t mode,
instance->pdata = data;
- goto cleanup_done;
-
- cleanup_appletviewer_mutex:
- g_mutex_free (data->appletviewer_mutex);
- data->appletviewer_mutex = NULL;
-
- // cleanup_instance_string:
- g_free (data->instance_id);
- data->instance_id = NULL;
-
- // cleanup applet tag:
- g_free (data->applet_tag);
- data->applet_tag = NULL;
-
- // cleanup_data:
- // Eliminate back-pointer to plugin instance.
- data->owner = NULL;
- (*browser_functions.memfree) (data);
- data = NULL;
-
- // Initialization failed so return a NULL pointer for the browser
- // data.
- instance->pdata = NULL;
-
cleanup_done:
- g_free (applet_tag);
- applet_tag = NULL;
g_free (read_message);
read_message = NULL;
g_free (documentbase);
@@ -834,7 +805,7 @@ ITNP_SetWindow (NPP instance, NPWindow* window)
// Now we have everything. Send this data to the Java side
plugin_send_initialization_message(
data->instance_id, (gulong) data->window_handle,
- data->window_width, data->window_height, data->applet_tag);
+ data->window_width, data->window_height, data->parameters_string);
g_mutex_unlock (data->appletviewer_mutex);
@@ -1694,159 +1665,67 @@ plugin_start_appletviewer (ITNPPluginData* data)
return error;
}
+
/*
- * Replaces certain characters (\r, \n, etc) with HTML escape equivalents.
- *
- * Return string is allocated on the heap. Caller assumes responsibility
- * for freeing the memory via free()
+ * Escape characters for passing to Java.
+ * "\n" for new line, "\\" for "\", "\:" for ";"
*/
-static char*
-encode_string(char* to_encode)
-{
-
- // Do nothing for an empty string
- if (to_encode == '\0')
- return to_encode;
-
- // worst case scenario -> all characters are newlines or
- // returns, each of which translates to 5 substitutions
- char* encoded = (char*) calloc(((strlen(to_encode)*5)+1), sizeof(char));
+std::string
+escape_parameter_string(const char* to_encode) {
+ std::string encoded;
- strcpy(encoded, "");
+ if (to_encode == NULL)
+ {
+ return encoded;
+ }
- for (int i=0; i < strlen(to_encode); i++)
+ size_t length = strlen(to_encode);
+ for (int i = 0; i < length; i++)
{
- if (to_encode[i] == '\r')
- encoded = strcat(encoded, "&#13;");
- else if (to_encode[i] == '\n')
- encoded = strcat(encoded, "&#10;");
- else if (to_encode[i] == '>')
- encoded = strcat(encoded, "&gt;");
- else if (to_encode[i] == '<')
- encoded = strcat(encoded, "&lt;");
- else if (to_encode[i] == '&')
- encoded = strcat(encoded, "&amp;");
- else if (to_encode[i] == '"')
- encoded = strcat(encoded, "&quot;");
+ if (to_encode[i] == '\n')
+ encoded += "\\n";
+ else if (to_encode[i] == '\\')
+ encoded += "\\\\";
+ else if (to_encode[i] == ';')
+ encoded += "\\:";
else
- {
- char* orig_char = (char*) calloc(2, sizeof(char));
- orig_char[0] = to_encode[i];
- orig_char[1] = '\0';
-
- strcat(encoded, orig_char);
-
- free(orig_char);
- orig_char = NULL;
- }
+ encoded += to_encode[i];
}
return encoded;
}
-// Build up the applet tag string that we'll send to the applet
-// viewer.
-static gchar*
-plugin_create_applet_tag (int16_t argc, char* argn[], char* argv[])
+/*
+ * Build a string containing an encoded list of parameters to send to the applet viewer.
+ * The parameters are separated as 'key1;value1;key2;value2;'. As well, they are
+ * separated and escaped as:
+ * "\n" for new line, "\\" for "\", "\:" for ";"
+ */
+std::string
+plugin_parameters_string (int argc, char* argn[], char* argv[])
{
- PLUGIN_DEBUG ("plugin_create_applet_tag\n");
-
- gchar* applet_tag = g_strdup ("<EMBED ");
- gchar* parameters = g_strdup ("");
+ PLUGIN_DEBUG ("plugin_parameters_string\n");
- for (int16_t i = 0; i < argc; i++)
- {
- gchar* argn_escaped = encode_string(argn[i]);
- gchar* argv_escaped = encode_string(argv[i]);
+ std::string parameters;
- if (!g_ascii_strcasecmp (argn_escaped, "code"))
- {
- gchar* code = g_strdup_printf ("CODE=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, code, NULL);
- g_free (code);
- code = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "java_code"))
- {
- gchar* java_code = g_strdup_printf ("JAVA_CODE=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, java_code, NULL);
- g_free (java_code);
- java_code = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "codebase"))
- {
- gchar* codebase = g_strdup_printf ("CODEBASE=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, codebase, NULL);
- g_free (codebase);
- codebase = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "java_codebase"))
- {
- gchar* java_codebase = g_strdup_printf ("JAVA_CODEBASE=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, java_codebase, NULL);
- g_free (java_codebase);
- java_codebase = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "classid"))
- {
- gchar* classid = g_strdup_printf ("CLASSID=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, classid, NULL);
- g_free (classid);
- classid = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "archive"))
- {
- gchar* archive = g_strdup_printf ("ARCHIVE=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, archive, NULL);
- g_free (archive);
- archive = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "java_archive"))
- {
- gchar* java_archive = g_strdup_printf ("JAVA_ARCHIVE=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, java_archive, NULL);
- g_free (java_archive);
- java_archive = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "width"))
- {
- gchar* width = g_strdup_printf ("width=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, width, NULL);
- g_free (width);
- width = NULL;
- }
- else if (!g_ascii_strcasecmp (argn_escaped, "height"))
+ for (int i = 0; i < argc; i++)
+ {
+ if (argv[i] != NULL)
{
- gchar* height = g_strdup_printf ("height=\"%s\" ", argv_escaped);
- applet_tag = g_strconcat (applet_tag, height, NULL);
- g_free (height);
- height = NULL;
- }
- else
- {
-
- if (argv_escaped != '\0')
- {
- parameters = g_strconcat (parameters, "<PARAM NAME=\"", argn_escaped,
- "\" VALUE=\"", argv_escaped, "\">", NULL);
- }
- }
-
- free(argn_escaped);
- free(argv_escaped);
+ std::string name_escaped = escape_parameter_string(argn[i]);
+ std::string value_escaped = escape_parameter_string(argv[i]);
- argn_escaped = NULL;
- argv_escaped = NULL;
+ //Encode parameters and send as 'key1;value1;key2;value2;' etc
+ parameters += name_escaped;
+ parameters += ';';
+ parameters += value_escaped;
+ parameters += ';';
}
+ }
- applet_tag = g_strconcat (applet_tag, ">", parameters, "</EMBED>", NULL);
-
- g_free (parameters);
- parameters = NULL;
-
- PLUGIN_DEBUG ("plugin_create_applet_tag return\n");
+ PLUGIN_DEBUG ("plugin_parameters_string return\n");
- return applet_tag;
+ return parameters;
}
// plugin_send_message_to_appletviewer must be called while holding
@@ -2057,8 +1936,8 @@ plugin_data_destroy (NPP instance)
tofree->instance_id = NULL;
// cleanup applet tag
- g_free (tofree->applet_tag);
- tofree->applet_tag = NULL;
+ g_free (tofree->parameters_string);
+ tofree->parameters_string = NULL;
g_free(tofree->source);
tofree->source = NULL;
@@ -2537,7 +2416,7 @@ get_scriptable_object(NPP instance)
// a 0 handle
if (!data->window_handle)
{
- plugin_send_initialization_message(data->instance_id, 0, 0, 0, data->applet_tag);
+ plugin_send_initialization_message(data->instance_id, 0, 0, 0, data->parameters_string);
}
java_result = java_request.getAppletObjectInstance(id_str);
diff --git a/plugin/icedteanp/IcedTeaNPPlugin.h b/plugin/icedteanp/IcedTeaNPPlugin.h
index 187aede..d009e70 100644
--- a/plugin/icedteanp/IcedTeaNPPlugin.h
+++ b/plugin/icedteanp/IcedTeaNPPlugin.h
@@ -66,8 +66,8 @@ struct ITNPPluginData
{
// A unique identifier for this plugin window.
gchar* instance_id;
- // The applet tag sent to Java side
- gchar* applet_tag;
+ // The parameter list string sent to Java side
+ gchar* parameters_string;
// Mutex to protect appletviewer_alive.
GMutex* appletviewer_mutex;
// Back-pointer to the plugin instance to which this data belongs.
diff --git a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
index f9d9422..611ed56 100644
--- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
@@ -70,7 +70,6 @@ import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
-import java.awt.Toolkit;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
@@ -87,6 +86,7 @@ import java.lang.reflect.InvocationTargetException;
import java.net.SocketPermission;
import java.net.URI;
import java.net.URL;
+import java.net.URLConnection;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.PrivilegedAction;
@@ -107,6 +107,7 @@ import java.util.concurrent.locks.ReentrantLock;
import javax.swing.SwingUtilities;
import net.sourceforge.jnlp.NetxPanel;
+import net.sourceforge.jnlp.PluginParameters;
import net.sourceforge.jnlp.runtime.JNLPClassLoader;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
@@ -129,14 +130,14 @@ class PluginAppletPanelFactory {
public AppletPanel createPanel(PluginStreamHandler streamhandler,
final int identifier,
- final long handle, int x, int y,
+ final long handle,
final URL doc,
- final Hashtable<String, String> atts) {
+ final PluginParameters params) {
final NetxPanel panel = AccessController.doPrivileged(new PrivilegedAction<NetxPanel>() {
public NetxPanel run() {
- NetxPanel panel = new NetxPanel(doc, atts, false);
+ NetxPanel panel = new NetxPanel(doc, params, false);
NetxPanel.debug("Using NetX panel");
- PluginDebug.debug(atts.toString());
+ PluginDebug.debug(params.toString());
return panel;
}
});
@@ -146,14 +147,13 @@ class PluginAppletPanelFactory {
// isn't the case, the awt eventqueue thread's context classloader
// won't be set to a JNLPClassLoader, and when an applet class needs
// to be loaded from the awt eventqueue, it won't be found.
- final int width = Integer.parseInt(atts.get("width"));
- final int height = Integer.parseInt(atts.get("height"));
Thread panelInit = new Thread(panel.getThreadGroup(), new Runnable() {
@Override public void run() {
panel.createNewAppContext();
// create the frame.
- PluginDebug.debug("X and Y are: " + width + " " + height);
- panel.setAppletViewerFrame(PluginAppletViewer.framePanel(identifier,handle, width, height, panel));
+ PluginDebug.debug("X and Y are: " + params.getWidth() + " " + params.getHeight());
+ panel.setAppletViewerFrame(PluginAppletViewer.framePanel(identifier, handle,
+ params.getWidth(), params.getHeight(), panel));
panel.init();
// Start the applet
@@ -194,7 +194,7 @@ class PluginAppletPanelFactory {
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
- panel.getParent().setSize(width, height);
+ panel.getParent().setSize(params.getWidth(), params.getHeight());
}
});
} catch (InvocationTargetException ite) {
@@ -599,18 +599,28 @@ public class PluginAppletViewer extends XEmbeddedFrame
int spaceLocation = message.indexOf(' ', "tag".length() + 1);
String documentBase =
UrlUtil.decode(message.substring("tag".length() + 1, spaceLocation));
- String tag = message.substring(spaceLocation + 1);
+ String paramString = message.substring(spaceLocation + 1);
PluginDebug.debug("Handle = ", handle, "\n",
"Width = ", width, "\n",
"Height = ", height, "\n",
"DocumentBase = ", documentBase, "\n",
- "Tag = ", tag);
+ "Params = ", paramString);
- PluginAppletViewer.parse
- (identifier, handle, width, height,
- new StringReader(tag),
- new URL(documentBase));
+ PluginAppletPanelFactory factory = new PluginAppletPanelFactory();
+ AppletMessageHandler amh = new AppletMessageHandler("appletviewer");
+ URL url = new URL(documentBase);
+ URLConnection conn = url.openConnection();
+ /* The original URL may have been redirected - this
+ * sets it to whatever URL/codebase we ended up getting
+ */
+ url = conn.getURL();
+
+ PluginParameters params = new PluginParameterParser().parse(width, height, paramString);
+
+ // Let user know we are starting up
+ streamhandler.write("instance " + identifier + " status " + amh.getMessage("status.start"));
+ factory.createPanel(streamhandler, identifier, handle, url, params);
long maxTimeToSleep = APPLET_TIMEOUT;
appletsLock.lock();
@@ -1546,24 +1556,6 @@ public class PluginAppletViewer extends XEmbeddedFrame
}
/**
- * Decodes the string (converts html escapes into proper characters)
- *
- * @param toDecode The string to decode
- * @return The decoded string
- */
- public static String decodeString(String toDecode) {
-
- toDecode = toDecode.replace("&gt;", ">");
- toDecode = toDecode.replace("&lt;", "<");
- toDecode = toDecode.replace("&amp;", "&");
- toDecode = toDecode.replace("&#10;", "\n");
- toDecode = toDecode.replace("&#13;", "\r");
- toDecode = toDecode.replace("&quot;", "\"");
-
- return toDecode;
- }
-
- /**
* System parameters.
*/
static Hashtable<String, String> systemParam = new Hashtable<String, String>();
@@ -1580,76 +1572,14 @@ public class PluginAppletViewer extends XEmbeddedFrame
}
/**
- * Print the HTML tag.
- */
- public static void printTag(PrintStream out, Hashtable<String, String> atts) {
- out.print("<applet");
-
- String v = atts.get("codebase");
- if (v != null) {
- out.print(" codebase=\"" + v + "\"");
- }
-
- v = atts.get("code");
- if (v == null) {
- v = "applet.class";
- }
- out.print(" code=\"" + v + "\"");
- v = atts.get("width");
- if (v == null) {
- v = "150";
- }
- out.print(" width=" + v);
-
- v = atts.get("height");
- if (v == null) {
- v = "100";
- }
- out.print(" height=" + v);
-
- v = atts.get("name");
- if (v != null) {
- out.print(" name=\"" + v + "\"");
- }
- out.println(">");
-
- // A very slow sorting algorithm
- int len = atts.size();
- String params[] = new String[len];
- len = 0;
- for (Enumeration<String> e = atts.keys(); e.hasMoreElements();) {
- String param = e.nextElement();
- int i = 0;
- for (; i < len; i++) {
- if (params[i].compareTo(param) >= 0) {
- break;
- }
- }
- System.arraycopy(params, i, params, i + 1, len - i);
- params[i] = param;
- len++;
- }
-
- for (int i = 0; i < len; i++) {
- String param = params[i];
- if (systemParam.get(param) == null) {
- out.println("<param name=" + param +
- " value=\"" + atts.get(param) + "\">");
- }
- }
- out.println("</applet>");
- }
-
- /**
* Make sure the atrributes are uptodate.
*/
public void updateAtts() {
Dimension d = panel.getSize();
Insets in = panel.getInsets();
- panel.atts.put("width",
- Integer.valueOf(d.width - (in.left + in.right)).toString());
- panel.atts.put("height",
- Integer.valueOf(d.height - (in.top + in.bottom)).toString());
+ int width = d.width - (in.left + in.right);
+ int height = d.height - (in.top + in.bottom);
+ panel.updateSizeInAtts(height, width);
}
/**
@@ -1796,412 +1726,6 @@ public class PluginAppletViewer extends XEmbeddedFrame
return appletPanels.size();
}
- /**
- * Scan spaces.
- */
- public static void skipSpace(int[] c, Reader in) throws IOException {
- while ((c[0] >= 0) &&
- ((c[0] == ' ') || (c[0] == '\t') || (c[0] == '\n') || (c[0] == '\r'))) {
- c[0] = in.read();
- }
- }
-
- /**
- * Scan identifier
- */
- public static String scanIdentifier(int[] c, Reader in) throws IOException {
- StringBuilder buf = new StringBuilder();
-
- if (c[0] == '!') {
- // Technically, we should be scanning for '!--' but we are reading
- // from a stream, and there is no way to peek ahead. That said,
- // a ! at this point can only mean comment here afaik, so we
- // should be okay
- skipComment(c, in);
- return "";
- }
-
- while (true) {
- if (((c[0] >= 'a') && (c[0] <= 'z')) ||
- ((c[0] >= 'A') && (c[0] <= 'Z')) ||
- ((c[0] >= '0') && (c[0] <= '9')) || (c[0] == '_')) {
- buf.append((char) c[0]);
- c[0] = in.read();
- } else {
- return buf.toString();
- }
- }
- }
-
- public static void skipComment(int[] c, Reader in) throws IOException {
- StringBuilder buf = new StringBuilder();
- boolean commentHeaderPassed = false;
- c[0] = in.read();
- buf.append((char) c[0]);
-
- while (true) {
- if (c[0] == '-' && (c[0] = in.read()) == '-') {
- buf.append((char) c[0]);
- if (commentHeaderPassed) {
- // -- encountered ... is > next?
- if ((c[0] = in.read()) == '>') {
- buf.append((char) c[0]);
-
- PluginDebug.debug("Comment skipped: ", buf.toString());
-
- // comment skipped.
- return;
- }
- } else {
- // first -- is part of <!-- ... , just mark that we have passed it
- commentHeaderPassed = true;
- }
-
- } else if (commentHeaderPassed == false) {
- buf.append((char) c[0]);
- PluginDebug.debug("Warning: Attempted to skip comment, but this tag does not appear to be a comment: ", buf.toString());
- return;
- }
-
- c[0] = in.read();
- buf.append((char) c[0]);
- }
- }
-
- /**
- * Scan tag
- */
- public static Hashtable<String, String> scanTag(int[] c, Reader in) throws IOException {
- Hashtable<String, String> atts = new Hashtable<String, String>();
- skipSpace(c, in);
- while (c[0] >= 0 && c[0] != '>') {
- String att = decodeString(scanIdentifier(c, in));
- String val = "";
- skipSpace(c, in);
- if (c[0] == '=') {
- int quote = -1;
- c[0] = in.read();
- skipSpace(c, in);
- if ((c[0] == '\'') || (c[0] == '\"')) {
- quote = c[0];
- c[0] = in.read();
- }
- StringBuilder buf = new StringBuilder();
- while ((c[0] > 0) &&
- (((quote < 0) && (c[0] != ' ') && (c[0] != '\t') &&
- (c[0] != '\n') && (c[0] != '\r') && (c[0] != '>'))
- || ((quote >= 0) && (c[0] != quote)))) {
- buf.append((char) c[0]);
- c[0] = in.read();
- }
- if (c[0] == quote) {
- c[0] = in.read();
- }
- skipSpace(c, in);
- val = decodeString(buf.toString());
- }
-
- PluginDebug.debug("PUT ", att, " = '", val, "'");
- atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val);
-
- while (true) {
- if ((c[0] == '>') || (c[0] < 0) ||
- ((c[0] >= 'a') && (c[0] <= 'z')) ||
- ((c[0] >= 'A') && (c[0] <= 'Z')) ||
- ((c[0] >= '0') && (c[0] <= '9')) || (c[0] == '_'))
- break;
- c[0] = in.read();
- }
- //skipSpace(in);
- }
- return atts;
- }
-
- // private static final == inline
- private static final boolean isInt(Object o) {
- boolean isInt = false;
- try {
- Integer.parseInt((String) o);
- isInt = true;
- } catch (Exception e) {
- // don't care
- }
-
- return isInt;
- }
-
- /* values used for placement of AppletViewer's frames */
- private static int x = 0;
- private static int y = 0;
- private static final int XDELTA = 30;
- private static final int YDELTA = XDELTA;
-
- static String encoding = null;
-
- /**
- * Scan an html file for <applet> tags
- */
- public static void parse(int identifier, long handle, String width, String height, Reader in, URL url, String enc)
- throws IOException {
- encoding = enc;
- parse(identifier, handle, width, height, in, url, System.out, new PluginAppletPanelFactory());
- }
-
- public static void parse(int identifier, long handle, String width, String height, Reader in, URL url)
- throws PrivilegedActionException {
-
- final int fIdentifier = identifier;
- final long fHandle = handle;
- final String fWidth = width;
- final String fHeight = height;
- final Reader fIn = in;
- final URL fUrl = url;
- AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
- public Void run() throws IOException {
- parse(fIdentifier, fHandle, fWidth, fHeight, fIn, fUrl,
- System.out, new PluginAppletPanelFactory());
- return null;
- }
- });
- }
-
- @SuppressWarnings("unused")
- public static void parse(int identifier, long handle, String width,
- String height, Reader in, URL url,
- PrintStream statusMsgStream,
- PluginAppletPanelFactory factory)
- throws IOException {
- boolean isObjectTag = false;
- boolean objectTagAlreadyParsed = false;
-
- // The current character
- // FIXME: This is an evil hack to force pass-by-reference.. the
- // parsing code needs to be rewritten from scratch to prevent such
- //a need
- int[] c = new int[1];
-
- // warning messages
- String requiresNameWarning = amh.getMessage("parse.warning.requiresname");
- String paramOutsideWarning = amh.getMessage("parse.warning.paramoutside");
- String appletRequiresCodeWarning = amh.getMessage("parse.warning.applet.requirescode");
- String appletRequiresHeightWarning = amh.getMessage("parse.warning.applet.requiresheight");
- String appletRequiresWidthWarning = amh.getMessage("parse.warning.applet.requireswidth");
- String objectRequiresCodeWarning = amh.getMessage("parse.warning.object.requirescode");
- String objectRequiresHeightWarning = amh.getMessage("parse.warning.object.requiresheight");
- String objectRequiresWidthWarning = amh.getMessage("parse.warning.object.requireswidth");
- String embedRequiresCodeWarning = amh.getMessage("parse.warning.embed.requirescode");
- String embedRequiresHeightWarning = amh.getMessage("parse.warning.embed.requiresheight");
- String embedRequiresWidthWarning = amh.getMessage("parse.warning.embed.requireswidth");
- String appNotLongerSupportedWarning = amh.getMessage("parse.warning.appnotLongersupported");
-
- java.net.URLConnection conn = url.openConnection();
- /* The original URL may have been redirected - this
- * sets it to whatever URL/codebase we ended up getting
- */
- url = conn.getURL();
-
- int ydisp = 1;
- Hashtable<String, String> atts = null;
-
- while (true) {
- c[0] = in.read();
- if (c[0] == -1)
- break;
-
- if (c[0] == '<') {
- c[0] = in.read();
- if (c[0] == '/') {
- c[0] = in.read();
- String nm = scanIdentifier(c, in);
- if (nm.equalsIgnoreCase("applet") ||
- nm.equalsIgnoreCase("object") ||
- nm.equalsIgnoreCase("embed")) {
-
- // We can't test for a code tag until </OBJECT>
- // because it is a parameter, not an attribute.
- if (isObjectTag) {
- if (atts.get("code") == null && atts.get("object") == null) {
- statusMsgStream.println(objectRequiresCodeWarning);
- atts = null;
- }
- }
-
- if (atts != null) {
- // XXX 5/18 In general this code just simply
- // shouldn't be part of parsing. It's presence
- // causes things to be a little too much of a
- // hack.
-
- // Let user know we are starting up
- streamhandler.write("instance " + identifier + " status " + amh.getMessage("status.start"));
- factory.createPanel(streamhandler, identifier, handle, x, y, url, atts);
-
- x += XDELTA;
- y += YDELTA;
- // make sure we don't go too far!
- Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
- if ((x > d.width - 300) || (y > d.height - 300)) {
- x = 0;
- y = 2 * ydisp * YDELTA;
- ydisp++;
- }
- }
- atts = null;
- isObjectTag = false;
- }
- } else {
- String nm = scanIdentifier(c, in);
- if (nm.equalsIgnoreCase("param")) {
- Hashtable<String, String> t = scanTag(c, in);
- String att = t.get("name");
-
- if (att == null) {
- statusMsgStream.println(requiresNameWarning);
- } else {
- String val = t.get("value");
- if (val == null) {
- statusMsgStream.println(requiresNameWarning);
- } else {
- PluginDebug.debug("PUT ", att, " = ", val);
- atts.put(att.toLowerCase(), val);
- }
- }
- } else if (nm.equalsIgnoreCase("applet")) {
- atts = scanTag(c, in);
-
- // If there is a classid and no code tag present, transform it to code tag
- if (atts.get("code") == null && atts.get("classid") != null
- && !(atts.get("classid")).startsWith("clsid:")) {
- atts.put("code", atts.get("classid"));
- }
-
- // remove java: from code tag
- if (atts.get("code") != null && (atts.get("code")).startsWith("java:")) {
- atts.put("code", (atts.get("code")).substring(5));
- }
-
- if (atts.get("code") == null && atts.get("object") == null) {
- statusMsgStream.println(appletRequiresCodeWarning);
- atts = null;
- }
-
- if (atts.get("width") == null || !isInt(atts.get("width"))) {
- atts.put("width", width);
- }
-
- if (atts.get("height") == null || !isInt(atts.get("height"))) {
- atts.put("height", height);
- }
- } else if (nm.equalsIgnoreCase("object")) {
- isObjectTag = true;
-
- // Once code is set, additional nested objects are ignored
- if (!objectTagAlreadyParsed) {
- objectTagAlreadyParsed = true;
- atts = scanTag(c, in);
- }
-
- // If there is a classid and no code tag present, transform it to code tag
- if (atts.get("code") == null && atts.get("classid") != null
- && !(atts.get("classid")).startsWith("clsid:")) {
- atts.put("code", atts.get("classid"));
- }
-
- // remove java: from code tag
- if (atts.get("code") != null && (atts.get("code")).startsWith("java:")) {
- atts.put("code", (atts.get("code")).substring(5));
- }
-
- // java_* aliases override older names:
- // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-ie
- if (atts.get("java_code") != null) {
- atts.put("code", (atts.get("java_code")));
- }
-
- if (atts.containsKey("code")) {
- objectTagAlreadyParsed = true;
- }
-
- if (atts.get("java_codebase") != null) {
- atts.put("codebase", (atts.get("java_codebase")));
- }
-
- if (atts.get("java_archive") != null) {
- atts.put("archive", (atts.get("java_archive")));
- }
-
- if (atts.get("java_object") != null) {
- atts.put("object", (atts.get("java_object")));
- }
-
- if (atts.get("java_type") != null) {
- atts.put("type", (atts.get("java_type")));
- }
-
- if (atts.get("width") == null || !isInt(atts.get("width"))) {
- atts.put("width", width);
- }
-
- if (atts.get("height") == null || !isInt(atts.get("height"))) {
- atts.put("height", height);
- }
- } else if (nm.equalsIgnoreCase("embed")) {
- atts = scanTag(c, in);
-
- // If there is a classid and no code tag present, transform it to code tag
- if (atts.get("code") == null && atts.get("classid") != null
- && !(atts.get("classid")).startsWith("clsid:")) {
- atts.put("code", atts.get("classid"));
- }
-
- // remove java: from code tag
- if (atts.get("code") != null && (atts.get("code")).startsWith("java:")) {
- atts.put("code", (atts.get("code")).substring(5));
- }
-
- // java_* aliases override older names:
- // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-nav
- if (atts.get("java_code") != null) {
- atts.put("code", (atts.get("java_code")));
- }
-
- if (atts.get("java_codebase") != null) {
- atts.put("codebase", (atts.get("java_codebase")));
- }
-
- if (atts.get("java_archive") != null) {
- atts.put("archive", (atts.get("java_archive")));
- }
-
- if (atts.get("java_object") != null) {
- atts.put("object", (atts.get("java_object")));
- }
-
- if (atts.get("java_type") != null) {
- atts.put("type", (atts.get("java_type")));
- }
-
- if (atts.get("code") == null && atts.get("object") == null) {
- statusMsgStream.println(embedRequiresCodeWarning);
- atts = null;
- }
-
- if (atts.get("width") == null || !isInt(atts.get("width"))) {
- atts.put("width", width);
- }
-
- if (atts.get("height") == null || !isInt(atts.get("height"))) {
- atts.put("height", height);
- }
-
- }
- }
- }
- }
- in.close();
- }
-
- private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer");
private static void checkConnect(URL url) {
SecurityManager security = System.getSecurityManager();
diff --git a/plugin/icedteanp/java/sun/applet/PluginParameterParser.java b/plugin/icedteanp/java/sun/applet/PluginParameterParser.java
new file mode 100644
index 0000000..9ce578f
--- /dev/null
+++ b/plugin/icedteanp/java/sun/applet/PluginParameterParser.java
@@ -0,0 +1,90 @@
+package sun.applet;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sourceforge.jnlp.PluginParameters;
+
+class PluginParameterParser {
+ static private final char DELIMITER_ESCAPE = ':';
+ static private final String KEY_VALUE_DELIMITER = ";";
+
+ /**
+ * Unescape characters passed from C++.
+ * Specifically, "\n" -> new line, "\\" -> "\", "\:" -> ";"
+ *
+ * @param str The string to unescape
+ * @return The unescaped string
+ */
+ static String unescapeString(String str) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < str.length(); i++) {
+ char chr = str.charAt(i);
+ if (chr != '\\') {
+ sb.append(chr);
+ } else {
+ i++; // Skip ahead one
+ chr = str.charAt(i);
+ if (chr == 'n') {
+ sb.append('\n');
+ } else if (chr == '\\') {
+ sb.append('\\');
+ } else if (chr == DELIMITER_ESCAPE) {
+ sb.append(KEY_VALUE_DELIMITER);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Parse semi-colon delimited key-value pairs.
+ * @param keyvalString the escaped, semicolon-delimited, string
+ * @return a map of the keys to the values
+ */
+ static Map<String, String> parseEscapedKeyValuePairs(String keyvalString) {
+ // Split on ';', ensuring empty strings at end are kept
+ String[] strs = keyvalString.split(KEY_VALUE_DELIMITER, -1 /* Keep empty strings */);
+ System.out.println("Split array: " + Arrays.toString(strs));
+
+ Map<String, String> attributes = new HashMap<String, String>();
+
+ /* Note that we will typically have one empty string at end */
+ for (int i = 0; i < strs.length - 1; i += 2) {
+ String key = unescapeString(strs[i]).toLowerCase();
+ String value = unescapeString(strs[i + 1]);
+ attributes.put(key, value);
+ }
+
+ return attributes;
+ }
+
+ static boolean isInt(String s) {
+ return s.matches("^-?\\d+$");
+ }
+
+ /**
+ * Parsers parameters given a string containing
+ * parameters in quotes.
+ *
+ * @param width default applet width
+ * @param height default applet height
+ * @param parameterString the parameters
+ * @return the attributes in a hash table
+ */
+ public PluginParameters parse(String width,
+ String height, String parameterString) {
+ Map<String, String> params = parseEscapedKeyValuePairs(parameterString);
+
+ if (params.get("width") == null || !isInt(params.get("width"))) {
+ params.put("width", width);
+ }
+
+ if (params.get("height") == null || !isInt(params.get("height"))) {
+ params.put("height", height);
+ }
+
+ return new PluginParameters(params);
+ }
+}
diff --git a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
index 9d77564..1ad1698 100644
--- a/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
+++ b/tests/cpp-unit-tests/IcedTeaPluginUtilsTest.cc
@@ -48,7 +48,7 @@ TEST(NPVariantAsString) {
STRINGZ_TO_NPVARIANT("test", var);
std::string cppstr = IcedTeaPluginUtilities::NPVariantAsString(var);
- CHECK(cppstr == "test");
+ CHECK_EQUAL("test", cppstr);
}
diff --git a/tests/cpp-unit-tests/PluginParametersTest.cc b/tests/cpp-unit-tests/PluginParametersTest.cc
new file mode 100644
index 0000000..e0136e4
--- /dev/null
+++ b/tests/cpp-unit-tests/PluginParametersTest.cc
@@ -0,0 +1,93 @@
+/* Copyright (C) 2012 Red Hat
+
+ 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; either version 2, or (at your option)
+ any later version.
+
+ 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. */
+
+/******************************************************************************
+ * Unit tests for functions related to sending applet parameters *
+ * (key value pairs). *
+ ******************************************************************************/
+
+#include <UnitTest++.h>
+
+#include "IcedTeaNPPlugin.h"
+
+
+/* Not normally exposed */
+std::string escape_parameter_string(const char* to_encode);
+
+TEST(escape_parameter_string) {
+ CHECK_EQUAL("\\n", escape_parameter_string("\n"));
+ CHECK_EQUAL("\\\\", escape_parameter_string("\\"));
+ CHECK_EQUAL("\\:", escape_parameter_string(";"));
+
+ CHECK_EQUAL(std::string("test") + "\\n" + "\\\\" + "\\:",
+ escape_parameter_string("test\n\\;"));
+}
+
+/* Not normally exposed */
+std::string plugin_parameters_string(int argc, char* argn[], char* argv[]);
+
+TEST(plugin_parameters_string) {
+
+ /* test empty */{
+ const char* argn[] = { "" };
+ const char* argv[] = { "" };
+ CHECK_EQUAL("",
+ plugin_parameters_string(0, (char**)argn, (char**)argv));
+ }
+
+ /* test simple key & value */{
+ const char* argn[] = { "key" };
+ const char* argv[] = { "value" };
+ CHECK_EQUAL("key;value;",
+ plugin_parameters_string(1, (char**)argn, (char**)argv));
+ }
+
+ /* test key & value characters that require escaping */{
+ const char* argn[] = { "key\\" };
+ const char* argv[] = { "value;" };
+ CHECK_EQUAL("key\\\\;value\\:;",
+ plugin_parameters_string(1, (char**)argn, (char**)argv));
+ }
+
+ /* multiple key & value pairs that require escaping*/{
+ const char* argn[] = { "key1\\", "key2\\" };
+ const char* argv[] = { "value1;", "value2;" };
+ CHECK_EQUAL("key1\\\\;value1\\:;key2\\\\;value2\\:;",
+ plugin_parameters_string(2, (char**)argn, (char**)argv));
+ }
+}
+
+
diff --git a/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java b/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java
index e9069f2..9015acf 100644
--- a/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java
+++ b/tests/netx/unit/net/sourceforge/jnlp/PluginBridgeTest.java
@@ -29,6 +29,7 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.Map;
import java.util.Hashtable;
import java.util.List;
import junit.framework.Assert;
@@ -64,14 +65,20 @@ public class PluginBridgeTest {
}
}
+ static private PluginParameters createValidParamObject() {
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("code", ""); // Avoids an exception being thrown
+ return new PluginParameters(params);
+ }
+
@Test
public void testAbsoluteJNLPHref() throws MalformedURLException, Exception {
URL codeBase = new URL("http://undesired.absolute.codebase.com");
String absoluteLocation = "http://absolute.href.com/test.jnlp";
- Hashtable<String, String> atts = new Hashtable<String, String>();
- atts.put("jnlp_href", absoluteLocation);
+ PluginParameters params = createValidParamObject();
+ params.put("jnlp_href", absoluteLocation);
MockJNLPCreator mockCreator = new MockJNLPCreator();
- PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, atts, "", mockCreator);
+ PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, params, mockCreator);
assertEquals(absoluteLocation, mockCreator.getJNLPHref().toExternalForm());
}
@@ -79,12 +86,12 @@ public class PluginBridgeTest {
public void testRelativeJNLPHref() throws MalformedURLException, Exception {
URL codeBase = new URL("http://desired.absolute.codebase.com/");
String relativeLocation = "sub/dir/test.jnlp";
- Hashtable<String, String> atts = new Hashtable<String, String>();
- atts.put("jnlp_href", relativeLocation);
+ PluginParameters params = createValidParamObject();
+ params.put("jnlp_href", relativeLocation);
MockJNLPCreator mockCreator = new MockJNLPCreator();
- PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, atts, "", mockCreator);
+ PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, params, mockCreator);
assertEquals(codeBase.toExternalForm() + relativeLocation,
- mockCreator.getJNLPHref().toExternalForm());
+ mockCreator.getJNLPHref().toExternalForm());
}
@Test
@@ -92,12 +99,12 @@ public class PluginBridgeTest {
String desiredDomain = "http://desired.absolute.codebase.com";
URL codeBase = new URL(desiredDomain + "/undesired/sub/dir");
String relativeLocation = "/app/test/test.jnlp";
- Hashtable<String, String> atts = new Hashtable<String, String>();
- atts.put("jnlp_href", relativeLocation);
+ PluginParameters params = createValidParamObject();
+ params.put("jnlp_href", relativeLocation);
MockJNLPCreator mockCreator = new MockJNLPCreator();
- PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, atts, "", mockCreator);
+ PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, params, mockCreator);
assertEquals(desiredDomain + relativeLocation,
- mockCreator.getJNLPHref().toExternalForm());
+ mockCreator.getJNLPHref().toExternalForm());
}
@Test
@@ -166,12 +173,12 @@ public class PluginBridgeTest {
"ICAgICAgLz4NCiAgICAgICAgICAgIDwvam5scD4=";
MockJNLPCreator mockCreator = new MockJNLPCreator();
- Hashtable<String, String> atts = new Hashtable<String, String>();
- atts.put("jnlp_href", relativeLocation);
- atts.put("jnlp_embedded", jnlpFileEncoded);
+ PluginParameters params = createValidParamObject();
+ params.put("jnlp_href", relativeLocation);
+ params.put("jnlp_embedded", jnlpFileEncoded);
String jnlpCodebase = "http://www.redhat.com";
- PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, atts, "", mockCreator);
+ PluginBridge pb = new PluginBridge(codeBase, null, "", "", 0, 0, params, mockCreator);
JARDesc[] jars = pb.getResources().getJARs();
//Check if there are two jars cached
@@ -239,11 +246,11 @@ public class PluginBridgeTest {
"ICAgICAgICAgICAgPC9qbmxwPg==";
MockJNLPCreator mockCreator = new MockJNLPCreator();
- Hashtable<String, String> atts = new Hashtable<String, String>();
- atts.put("jnlp_href", relativeLocation);
- atts.put("jnlp_embedded", jnlpFileEncoded);
+ PluginParameters params = createValidParamObject();
+ params.put("jnlp_href", relativeLocation);
+ params.put("jnlp_embedded", jnlpFileEncoded);
- PluginBridge pb = new PluginBridge(overwrittenCodebase, null, "", "", 0, 0, atts, "", mockCreator);
+ PluginBridge pb = new PluginBridge(overwrittenCodebase, null, "", "", 0, 0, params, mockCreator);
JARDesc[] jars = pb.getResources().getJARs();
//Check if there are two jars cached
@@ -268,12 +275,12 @@ public class PluginBridgeTest {
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);
+ PluginParameters params = createValidParamObject();
+ params.put("jnlp_href", relativeLocation);
+ params.put("jnlp_embedded", jnlpFileEncoded);
try {
- new PluginBridge(overwrittenCodebase, null, "", "", 0, 0, atts, "", mockCreator);
+ new PluginBridge(overwrittenCodebase, null, "", "", 0, 0, params, mockCreator);
} catch (Exception e) {
return;
}
diff --git a/tests/netx/unit/net/sourceforge/jnlp/PluginParametersTest.java b/tests/netx/unit/net/sourceforge/jnlp/PluginParametersTest.java
new file mode 100644
index 0000000..0e05b53
--- /dev/null
+++ b/tests/netx/unit/net/sourceforge/jnlp/PluginParametersTest.java
@@ -0,0 +1,114 @@
+package net.sourceforge.jnlp;
+
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+import org.junit.Test;
+
+public class PluginParametersTest {
+
+ @Test
+ public void testAttributeParseJavaPrefix() {
+ // java_* aliases override older names:
+ // http://java.sun.com/j2se/1.4.2/docs/guide/plugin/developer_guide/using_tags.html#in-nav
+
+ Map<String, String> rawParams;
+ Hashtable<String, String> params;
+
+ rawParams = new HashMap<String, String>();
+ rawParams.put("code", "codeValue");
+ rawParams.put("java_code", "java_codeValue");
+ params = PluginParameters.createParameterTable(rawParams);
+
+ assertEquals("java_codeValue", params.get("code"));
+
+ rawParams = new HashMap<String, String>();
+ rawParams.put("codebase", "codebaseValue");
+ rawParams.put("java_codebase", "java_codebaseValue");
+ params = PluginParameters.createParameterTable(rawParams);
+
+ assertEquals("java_codebaseValue", params.get("codebase"));
+
+ rawParams = new HashMap<String, String>();
+ rawParams.put("archive", "archiveValue");
+ rawParams.put("java_archive", "java_archiveValue");
+ params = PluginParameters.createParameterTable(rawParams);
+
+ assertEquals("java_archiveValue", params.get("archive"));
+
+ rawParams = new HashMap<String, String>();
+ rawParams.put("object", "objectValue");
+ rawParams.put("java_object", "java_objectValue");
+ params = PluginParameters.createParameterTable(rawParams);
+
+ assertEquals("java_objectValue", params.get("object"));
+
+ rawParams = new HashMap<String, String>();
+ rawParams.put("type", "typeValue");
+ rawParams.put("java_type", "java_typeValue");
+ params = PluginParameters.createParameterTable(rawParams);
+
+ assertEquals("java_typeValue", params.get("type"));
+ }
+
+ @Test
+ public void testEnsureJavaPrefixTakesPrecedence() {
+ Map<String, String> params;
+ params = new HashMap<String, String>();
+ params.put("test", "testValue");
+ params.put("java_test", "java_testValue");
+ PluginParameters.ensureJavaPrefixTakesPrecedence(params, "test");
+ assertEquals("java_testValue", params.get("test"));
+
+ params = new HashMap<String, String>();
+ params.put("test", "testValue");
+ PluginParameters.ensureJavaPrefixTakesPrecedence(params, "test");
+ assertEquals("testValue", params.get("test"));
+
+ params = new HashMap<String, String>();
+ params.put("java_test", "java_testValue");
+ PluginParameters.ensureJavaPrefixTakesPrecedence(params, "test");
+ assertEquals("java_testValue", params.get("test"));
+ }
+
+ @Test
+ public void testAttributeParseCodeAttribute() {
+ Map<String, String> rawParams;
+ Hashtable<String, String> params;
+
+ // Simple test of object tag being set
+ rawParams = new HashMap<String, String>();
+ rawParams.put("object", "objectValue");
+ params = PluginParameters.createParameterTable(rawParams);
+ assertEquals("objectValue", params.get("object"));
+
+ // Classid tag gets used as code tag
+ rawParams = new HashMap<String, String>();
+ rawParams.put("classid", "classidValue");
+ params = PluginParameters.createParameterTable(rawParams);
+ assertEquals("classidValue", params.get("code"));
+
+ // Java: gets stripped from code tag
+ rawParams = new HashMap<String, String>();
+ rawParams.put("code", "java:codeValue");
+ params = PluginParameters.createParameterTable(rawParams);
+ assertEquals("codeValue", params.get("code"));
+
+ // Classid tag gets used as code tag, and java: is stripped
+ rawParams = new HashMap<String, String>();
+ rawParams.put("classid", "java:classidValue");
+ params = PluginParameters.createParameterTable(rawParams);
+ assertEquals("classidValue", params.get("code"));
+
+ // Classid tag gets used as code tag, and clsid: is stripped
+ rawParams = new HashMap<String, String>();
+ rawParams.put("classid", "clsid:classidValue");
+ params = PluginParameters.createParameterTable(rawParams);
+ assertEquals(null, params.get("code"));
+
+ }
+
+}
diff --git a/tests/netx/unit/sun/applet/PluginParameterParserTest.java b/tests/netx/unit/sun/applet/PluginParameterParserTest.java
new file mode 100644
index 0000000..162d603
--- /dev/null
+++ b/tests/netx/unit/sun/applet/PluginParameterParserTest.java
@@ -0,0 +1,73 @@
+package sun.applet;
+
+import static org.junit.Assert.*;
+
+import java.util.Map;
+
+import net.sourceforge.jnlp.PluginParameters;
+
+import org.junit.Test;
+
+public class PluginParameterParserTest {
+
+ @Test
+ public void testIsInt() {
+ assertFalse(PluginParameterParser.isInt("1.0"));
+ assertFalse(PluginParameterParser.isInt("abc"));
+ assertTrue(PluginParameterParser.isInt("1"));
+ }
+
+ @Test
+ public void testUnescapeString() {
+ assertEquals("", PluginParameterParser.unescapeString(""));
+ assertEquals("\n", PluginParameterParser.unescapeString("\n"));
+ assertEquals("\\", PluginParameterParser.unescapeString("\\\\"));
+ assertEquals(";", PluginParameterParser.unescapeString("\\:"));
+
+ assertEquals("test\n\\;",
+ PluginParameterParser.unescapeString("test" + "\\n" + "\\\\" + "\\:"));
+
+ assertEquals("start\n;end\\;",
+ PluginParameterParser.unescapeString("start\\n\\:end\\\\;"));
+ }
+
+ @Test
+ public void testParseEscapedKeyValuePairs() {
+ Map<String, String> params;
+
+ params = PluginParameterParser.parseEscapedKeyValuePairs("key1;value1;KEY2\\:;value2\\\\;");
+ assertEquals(params.size(), 2);
+ assertEquals(params.get("key1"), "value1");
+ assertEquals(params.get("key2;"), "value2\\"); // ensure key is lowercased
+
+ params = PluginParameterParser.parseEscapedKeyValuePairs("");
+ assertEquals(params.size(), 0);
+
+ params = PluginParameterParser.parseEscapedKeyValuePairs("key;;");
+ assertEquals(params.size(), 1);
+ assertEquals(params.get("key"), "");
+
+ params = PluginParameterParser.parseEscapedKeyValuePairs(";value;");
+ assertEquals(params.size(), 1);
+ assertEquals(params.get(""), "value");
+ }
+
+ @Test
+ public void testAttributeParseWidthHeightAttributes() {
+ final String width = "1", height = "1";
+ final String codeKeyVal = "code;codeValue;";
+
+ PluginParameterParser parser = new PluginParameterParser();
+ PluginParameters params;
+
+ params = parser.parse(width, height, codeKeyVal);
+ assertEquals("1", params.get("width"));
+ assertEquals("1", params.get("height"));
+
+ //Test that width height are defaulted to in case of not-a-number attributes:
+ params = parser.parse(width, height, codeKeyVal + " width;NAN;height;NAN;");
+ assertEquals("1", params.get("width"));
+ assertEquals("1", params.get("height"));
+ }
+
+}