aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge/jnlp
diff options
context:
space:
mode:
authorDenis Lila <[email protected]>2011-04-29 16:58:05 -0400
committerDenis Lila <[email protected]>2011-04-29 16:58:05 -0400
commit56d85fafd578e28fc17211d28f4f0a701192e789 (patch)
tree163144e2f7b4a7dcf42d38e35decc0ece28a03fb /netx/net/sourceforge/jnlp
parentd11445dcf1ad408836766709c47f47ef2aec1d31 (diff)
Fix appcontext related plugin bugs.
Diffstat (limited to 'netx/net/sourceforge/jnlp')
-rw-r--r--netx/net/sourceforge/jnlp/Launcher.java17
-rw-r--r--netx/net/sourceforge/jnlp/NetxPanel.java89
-rw-r--r--netx/net/sourceforge/jnlp/PluginBridge.java32
-rw-r--r--netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java63
4 files changed, 79 insertions, 122 deletions
diff --git a/netx/net/sourceforge/jnlp/Launcher.java b/netx/net/sourceforge/jnlp/Launcher.java
index 2c0af48..988650b 100644
--- a/netx/net/sourceforge/jnlp/Launcher.java
+++ b/netx/net/sourceforge/jnlp/Launcher.java
@@ -32,7 +32,6 @@ import java.util.jar.JarFile;
import net.sourceforge.jnlp.cache.CacheUtil;
import net.sourceforge.jnlp.cache.UpdatePolicy;
-import net.sourceforge.jnlp.runtime.AppThreadGroup;
import net.sourceforge.jnlp.runtime.AppletInstance;
import net.sourceforge.jnlp.runtime.ApplicationInstance;
import net.sourceforge.jnlp.runtime.JNLPClassLoader;
@@ -702,7 +701,7 @@ public class Launcher {
throw new ClassNotFoundException("Can't do a codebase look up and there are no jars. Failing sooner rather than later");
}
- AppThreadGroup group = (AppThreadGroup) Thread.currentThread().getThreadGroup();
+ ThreadGroup group = Thread.currentThread().getThreadGroup();
String appletName = file.getApplet().getMainClass();
@@ -718,7 +717,6 @@ public class Launcher {
else
appletInstance = new AppletInstance(file, group, loader, applet, cont);
- group.setApplication(appletInstance);
loader.setApplication(appletInstance);
setContextClassLoaderForAllThreads(appletInstance.getThreadGroup(), appletInstance.getClassLoader());
@@ -765,10 +763,9 @@ public class Launcher {
protected ApplicationInstance createApplication(JNLPFile file) throws LaunchException {
try {
JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy);
- AppThreadGroup group = (AppThreadGroup) Thread.currentThread().getThreadGroup();
+ ThreadGroup group = Thread.currentThread().getThreadGroup();
ApplicationInstance app = new ApplicationInstance(file, group, loader);
- group.setApplication(app);
loader.setApplication(app);
return app;
@@ -784,16 +781,16 @@ public class Launcher {
* then this method simply returns the existing ThreadGroup. The applet
* ThreadGroup has to be created at an earlier point in the applet code.
*/
- protected AppThreadGroup createThreadGroup(JNLPFile file) {
- AppThreadGroup appThreadGroup = null;
+ protected ThreadGroup createThreadGroup(JNLPFile file) {
+ ThreadGroup tg = null;
if (file instanceof PluginBridge) {
- appThreadGroup = (AppThreadGroup) Thread.currentThread().getThreadGroup();
+ tg = Thread.currentThread().getThreadGroup();
} else {
- appThreadGroup = new AppThreadGroup(mainGroup, file.getTitle());
+ tg = new ThreadGroup(mainGroup, file.getTitle());
}
- return appThreadGroup;
+ return tg;
}
/**
diff --git a/netx/net/sourceforge/jnlp/NetxPanel.java b/netx/net/sourceforge/jnlp/NetxPanel.java
index 2d723d4..e8d43cd 100644
--- a/netx/net/sourceforge/jnlp/NetxPanel.java
+++ b/netx/net/sourceforge/jnlp/NetxPanel.java
@@ -23,12 +23,13 @@
package net.sourceforge.jnlp;
import net.sourceforge.jnlp.AppletLog;
-import net.sourceforge.jnlp.runtime.AppThreadGroup;
import net.sourceforge.jnlp.runtime.AppletInstance;
import net.sourceforge.jnlp.runtime.JNLPRuntime;
import java.net.URL;
import java.util.Hashtable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import sun.applet.AppletViewerPanel;
import sun.awt.SunToolkit;
@@ -44,9 +45,58 @@ public class NetxPanel extends AppletViewerPanel {
private boolean exitOnFailure = true;
private AppletInstance appInst = null;
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.
+ private static final ConcurrentMap<String, ThreadGroup> uKeyToTG =
+ new ConcurrentHashMap<String, ThreadGroup>();
+
+ // This map is actually a set (unfortunately there is no ConcurrentSet
+ // in java.util.concurrent). If KEY is in this map, then we know that
+ // an app context has been created for the panel that has uKey.equals(KEY),
+ // so we avoid creating it a second time for panels with the same uKey.
+ // Because it's a set, only the keys matter. However, we can't insert
+ // null values in because if we did, we couldn't use null checks to see
+ // if a key was absent before a putIfAbsent.
+ private static final ConcurrentMap<String, Boolean> appContextCreated =
+ new ConcurrentHashMap<String, Boolean>();
public NetxPanel(URL documentURL, Hashtable<String, String> atts) {
super(documentURL, atts);
+
+ /* 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") : "";
+
+ 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());
+ ThreadGroup tg = new ThreadGroup(Launcher.mainGroup, this.documentURL.toString());
+ uKeyToTG.putIfAbsent(this.uKey, tg);
}
// overloaded constructor, called when initialized via plugin
@@ -58,18 +108,6 @@ public class NetxPanel extends AppletViewerPanel {
}
@Override
- public void run() {
- /*
- * create an AppContext for this thread associated with this particular
- * plugin instance (which runs in a different thread group from the rest
- * of the plugin).
- */
- SunToolkit.createNewAppContext();
-
- super.run();
- }
-
- @Override
protected void showAppletException(Throwable t) {
/*
* Log any exceptions thrown while loading, initializing, starting,
@@ -78,7 +116,7 @@ public class NetxPanel extends AppletViewerPanel {
AppletLog.log(t);
super.showAppletException(t);
}
-
+
//Overriding to use Netx classloader. You might need to relax visibility
//in sun.applet.AppletPanel for runLoader().
protected void runLoader() {
@@ -90,7 +128,7 @@ public class NetxPanel extends AppletViewerPanel {
getCode(),
getWidth(),
getHeight(),
- atts);
+ atts, uKey);
doInit = true;
dispatchAppletEvent(APPLET_LOADING, null);
@@ -154,11 +192,7 @@ public class NetxPanel extends AppletViewerPanel {
}
}
- // when this was being done (incorrectly) in Launcher, the call was
- // new AppThreadGroup(mainGroup, file.getTitle());
- ThreadGroup tg = new AppThreadGroup(Launcher.mainGroup,
- this.documentURL.toString());
- handler = new Thread(tg, this);
+ handler = new Thread(getThreadGroup(), this);
handler.start();
}
@@ -174,4 +208,19 @@ public class NetxPanel extends AppletViewerPanel {
public boolean isAlive() {
return handler != null && handler.isAlive() && this.appletAlive;
}
+
+ public ThreadGroup getThreadGroup() {
+ return uKeyToTG.get(uKey);
+ }
+
+ public void createNewAppContext() {
+ if (Thread.currentThread().getThreadGroup() != getThreadGroup()) {
+ throw new RuntimeException("createNewAppContext called from the wrong thread.");
+ }
+ // 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)) {
+ SunToolkit.createNewAppContext();
+ }
+ }
}
diff --git a/netx/net/sourceforge/jnlp/PluginBridge.java b/netx/net/sourceforge/jnlp/PluginBridge.java
index cbb6be1..f4cfa1e 100644
--- a/netx/net/sourceforge/jnlp/PluginBridge.java
+++ b/netx/net/sourceforge/jnlp/PluginBridge.java
@@ -44,7 +44,8 @@ public class PluginBridge extends JNLPFile {
private boolean codeBaseLookup;
public PluginBridge(URL codebase, URL documentBase, String jar, String main,
- int width, int height, Hashtable<String, String> atts)
+ int width, int height, Hashtable<String, String> atts,
+ String uKey)
throws Exception {
specVersion = new Version("1.0");
fileVersion = new Version("1.1");
@@ -132,34 +133,7 @@ public class PluginBridge extends JNLPFile {
else
security = null;
- /* 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") : "";
-
- String archiveAttr = atts.get("archive") != null ?
- atts.get("archive") : "";
-
- this.uniqueKey = "codebase=" + codebaseAttr +
- "cache_archive=" + cache_archiveAttr +
- "java_archive=" + java_archiveAttr +
- "archive=" + archiveAttr;
-
+ this.uniqueKey = uKey;
usePack = false;
useVersion = false;
String jargs = atts.get("java_arguments");
diff --git a/netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java b/netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java
deleted file mode 100644
index f09bf36..0000000
--- a/netx/net/sourceforge/jnlp/runtime/AppThreadGroup.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-//
-// This library 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
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
-package net.sourceforge.jnlp.runtime;
-
-/**
- * Thread group for a JNLP application.
- *
- * @author <a href="mailto:[email protected]">Jon A. Maxwell (JAM)</a> - initial author
- * @version $Revision: 1.5 $
- */
-public class AppThreadGroup extends ThreadGroup {
-
- /** the app */
- private ApplicationInstance app = null;
-
- /**
- * Creates new JavaAppThreadGroup
- *
- * @param name of the App
- */
- public AppThreadGroup(ThreadGroup parent, String name) {
- super(parent, name);
- }
-
- /**
- * Sets the JNLP app this group is for; can only be called once.
- */
- public void setApplication(ApplicationInstance app) {
- if (this.app != null)
- throw new IllegalStateException("Application can only be set once");
-
- this.app = app;
- }
-
- /**
- * Returns the JNLP app for this thread group.
- */
- public ApplicationInstance getApplication() {
- return app;
- }
-
- /**
- * Handle uncaught exceptions for the app.
- */
- public void uncaughtException(Thread t, Throwable e) {
- super.uncaughtException(t, e);
- }
-
-}