aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDeepak Bhole <[email protected]>2011-03-04 17:34:32 -0500
committerDeepak Bhole <[email protected]>2011-03-04 17:34:32 -0500
commit0b38becc8ddeb3026d5fa0ca89713cb3e38ac430 (patch)
treeb73cf798610230ad338b43b6865766f840aa1279
parenteb116d00b1dfee2df7b1dc6191d388a4b0f4b846 (diff)
- PR475, RH604061: Allow applets from the same page to use the same classloader
-rw-r--r--ChangeLog28
-rw-r--r--NEWS1
-rw-r--r--netx/net/sourceforge/jnlp/PluginBridge.java7
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java118
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java12
-rw-r--r--plugin/icedteanp/java/sun/applet/PluginAppletViewer.java9
6 files changed, 162 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog
index 4d4d629..8545f9b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2011-03-04 Deepak Bhole <[email protected]>
+
+ * NEWS: Updated.
+ * netx/net/sourceforge/jnlp/PluginBridge.java (PluginBridge): Use
+ documentbase as a uniquekey so that the classloader may be shared by
+ applets from the same page.
+ * netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Added new
+ CodeBaseClassLoader class to load codebase (from path instead of a file)
+ classes.
+ (getInstance): Try to match file locations only for Web Start apps. For
+ plugin, merge the new loader into current one.
+ (enableCodeBase): Use the new addToCodeBaseLoader method.
+ (findLoadedClassAll): Search the codebase loader if the class was not
+ found in the file loaders.
+ (findClass): Likewise.
+ (getResource): Likewise.
+ (findResources): Likewise.
+ (merge): Merge codebase loaders.
+ (addToCodeBaseLoader): New method. Adds a given url to the codebase loader
+ if it is a path.
+ (CodeBaseClassLoader): New inner class. Extends URLClassLoader to expose
+ its protected methods like addURL.
+ * netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+ (getApplication): Accomodate the fact that the classloader for a class may
+ be a CodeBaseClassLoader.
+ * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java (run):
+ Likewise.
+
2011-03-03 Deepak Bhole <[email protected]>
* plugin/icedteanp/IcedTeaNPPlugin.cc
diff --git a/NEWS b/NEWS
index c0f5c82..9cb153d 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,7 @@ New in release 1.1 (2011-XX-XX):
- Use Firefox's proxy settings if possible
- RH669942: javaws fails to download version/packed files (missing support for jnlp.packEnabled and jnlp.versionEnabled)
* Plugin
+ - PR475, RH604061: Allow applets from the same page to use the same classloader
- PR612: NetDania application ends on java.security.AccessControlException: access denied (java.util.PropertyPermission browser read)
New in release 1.0 (2010-XX-XX):
diff --git a/netx/net/sourceforge/jnlp/PluginBridge.java b/netx/net/sourceforge/jnlp/PluginBridge.java
index 2cb5146..a3ef9f3 100644
--- a/netx/net/sourceforge/jnlp/PluginBridge.java
+++ b/netx/net/sourceforge/jnlp/PluginBridge.java
@@ -130,9 +130,10 @@ public class PluginBridge extends JNLPFile {
else
security = null;
- this.uniqueKey = Calendar.getInstance().getTimeInMillis() + "-" +
- Math.abs(((new java.util.Random()).nextInt())) + "-" +
- documentBase;
+ // Plugin needs to share classloaders so that applet instances from
+ // same page can communicate (there are applets known to require
+ // such communication for proper functionality)
+ this.uniqueKey = documentBase.toString();
}
public String getTitle() {
diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
index 841e874..aae8b8b 100644
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
@@ -145,6 +145,9 @@ public class JNLPClassLoader extends URLClassLoader {
/** Map of specific codesources to securitydesc */
private HashMap<URL, SecurityDesc> jarLocationSecurityMap =
new HashMap<URL, SecurityDesc>();
+
+ /** Loader for codebase (which is a path, rather than a file) */
+ private CodeBaseClassLoader codeBaseLoader;
/**
* Create a new JNLPClassLoader from the specified file.
@@ -276,10 +279,12 @@ public class JNLPClassLoader extends URLClassLoader {
try {
- // If base loader is null, or the baseloader's file and this
- // file is different, initialize a new loader
+
+ // A null baseloader implies that no loader has been created
+ // for this codebase/jnlp yet. Create one.
if (baseLoader == null ||
- !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation())) {
+ (file.isApplication() &&
+ !baseLoader.getJNLPFile().getFileLocation().equals(file.getFileLocation()))) {
loader = new JNLPClassLoader(file, policy);
@@ -303,6 +308,13 @@ public class JNLPClassLoader extends URLClassLoader {
} else {
// if key is same and locations match, this is the loader we want
+ if (!file.isApplication()) {
+ // If this is an applet, we do need to consider its loader
+ loader = new JNLPClassLoader(file, policy);
+
+ if (baseLoader != null)
+ baseLoader.merge(loader);
+ }
loader = baseLoader;
}
@@ -529,7 +541,7 @@ public class JNLPClassLoader extends URLClassLoader {
* loaded from the codebase are not cached.
*/
public void enableCodeBase() {
- addURL(file.getCodeBase()); // nothing happens if called more that once?
+ addToCodeBaseLoader(file.getCodeBase());
}
/**
@@ -958,8 +970,13 @@ public class JNLPClassLoader extends URLClassLoader {
if (result != null)
return result;
}
-
- return null;
+
+ // Result is still null. Return what the codebaseloader
+ // has (which returns null if it is not loaded there either)
+ if (codeBaseLoader != null)
+ return codeBaseLoader.findLoadedClassFromParent(name);
+ else
+ return null;
}
/**
@@ -1067,6 +1084,11 @@ public class JNLPClassLoader extends URLClassLoader {
}
}
+ // Try codebase loader
+ if (codeBaseLoader != null)
+ return codeBaseLoader.findClass(name);
+
+ // All else failed. Throw CNFE
throw new ClassNotFoundException(name);
}
@@ -1109,6 +1131,10 @@ public class JNLPClassLoader extends URLClassLoader {
for (int i = 1; i < loaders.length; i++)
if (result == null)
result = loaders[i].getResource(name);
+
+ // If result is still null, look in the codebase loader
+ if (result == null && codeBaseLoader != null)
+ result = codeBaseLoader.getResource(name);
return result;
}
@@ -1120,9 +1146,9 @@ public class JNLPClassLoader extends URLClassLoader {
@Override
public Enumeration<URL> findResources(String name) throws IOException {
Vector<URL> resources = new Vector<URL>();
+ Enumeration<URL> e;
for (int i = 0; i < loaders.length; i++) {
- Enumeration<URL> e;
if (loaders[i] == this)
e = super.findResources(name);
@@ -1133,6 +1159,14 @@ public class JNLPClassLoader extends URLClassLoader {
resources.add(e.nextElement());
}
+ // Add resources from codebase (only if nothing was found above,
+ // otherwise the server will get hammered)
+ if (resources.isEmpty() && codeBaseLoader != null) {
+ e = codeBaseLoader.findResources(name);
+ while (e.hasMoreElements())
+ resources.add(e.nextElement());
+ }
+
return resources.elements();
}
@@ -1250,6 +1284,9 @@ public class JNLPClassLoader extends URLClassLoader {
// jars
for (URL u : extLoader.getURLs())
addURL(u);
+
+ // Codebase
+ addToCodeBaseLoader(extLoader.file.getCodeBase());
// native search paths
for (File nativeDirectory : extLoader.getNativeDirectories())
@@ -1261,6 +1298,28 @@ public class JNLPClassLoader extends URLClassLoader {
}
}
+ /**
+ * Adds the given path to the path loader
+ *
+ * @param URL the path to add
+ * @throws IllegalArgumentException If the given url is not a path
+ */
+ private void addToCodeBaseLoader(URL u) {
+
+ // Only paths may be added
+ if (!u.getFile().endsWith("/")) {
+ throw new IllegalArgumentException("addToPathLoader only accepts path based URLs");
+ }
+
+ // If there is no loader yet, create one, else add it to the
+ // existing one (happens when called from merge())
+ if (codeBaseLoader == null) {
+ codeBaseLoader = new CodeBaseClassLoader(new URL[] { u }, this);
+ } else {
+ codeBaseLoader.addURL(u);
+ }
+ }
+
private DownloadOptions getDownloadOptionsForJar(JARDesc jar) {
boolean usePack = false;
boolean useVersion = false;
@@ -1283,4 +1342,49 @@ public class JNLPClassLoader extends URLClassLoader {
return new DownloadOptions(usePack, useVersion);
}
+ /*
+ * Helper class to expose protected URLClassLoader methods.
+ */
+
+ public class CodeBaseClassLoader extends URLClassLoader {
+
+ JNLPClassLoader parentJNLPClassLoader;
+
+ public CodeBaseClassLoader(URL[] urls, JNLPClassLoader cl) {
+ super(urls);
+ parentJNLPClassLoader = cl;
+ }
+
+ @Override
+ public void addURL(URL url) {
+ super.addURL(url);
+ }
+
+ @Override
+ public Class<?> findClass(String name) throws ClassNotFoundException {
+ return super.findClass(name);
+ }
+
+ /**
+ * Returns the output of super.findLoadedClass().
+ *
+ * The method is renamed because ClassLoader.findLoadedClass() is final
+ *
+ * @param name The name of the class to find
+ * @return Output of ClassLoader.findLoadedClass() which is the class if found, null otherwise
+ * @see java.lang.ClassLoader#findLoadedClass(String)
+ */
+ public Class<?> findLoadedClassFromParent(String name) {
+ return findLoadedClass(name);
+ }
+
+ /**
+ * Returns JNLPClassLoader that encompasses this loader
+ *
+ * @return parent JNLPClassLoader
+ */
+ public JNLPClassLoader getParentJNLPClassLoader() {
+ return parentJNLPClassLoader;
+ }
+ }
}
diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java b/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
index fca019e..26eb799 100644
--- a/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
@@ -199,8 +199,16 @@ class JNLPSecurityManager extends AWTSecurityManager {
// this needs to be tightened up
for (int i = 0; i < stack.length && i < maxDepth; i++) {
- if (stack[i].getClassLoader() instanceof JNLPClassLoader) {
- JNLPClassLoader loader = (JNLPClassLoader) stack[i].getClassLoader();
+ ClassLoader cl = stack[i].getClassLoader();
+
+ // Since we want to deal with JNLPClassLoader, extract it if this
+ // is a codebase loader
+ if (cl instanceof JNLPClassLoader.CodeBaseClassLoader)
+ cl = ((JNLPClassLoader.CodeBaseClassLoader) cl).getParentJNLPClassLoader();
+
+ if (cl instanceof JNLPClassLoader) {
+
+ JNLPClassLoader loader = (JNLPClassLoader) cl;
if (loader != null && loader.getApplication() != null) {
return loader.getApplication();
diff --git a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
index 38b8b96..bd3637f 100644
--- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
+++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
@@ -1646,7 +1646,14 @@ public class PluginAppletViewer extends XEmbeddedFrame
{
public void run()
{
- ThreadGroup tg = ((JNLPClassLoader) p.applet.getClass().getClassLoader()).getApplication().getThreadGroup();
+ ClassLoader cl = p.applet.getClass().getClassLoader();
+
+ // Since we want to deal with JNLPClassLoader, extract it if this
+ // is a codebase loader
+ if (cl instanceof JNLPClassLoader.CodeBaseClassLoader)
+ cl = ((JNLPClassLoader.CodeBaseClassLoader) cl).getParentJNLPClassLoader();
+
+ ThreadGroup tg = ((JNLPClassLoader) cl).getApplication().getThreadGroup();
appletShutdown(p);
appletPanels.removeElement(p);