aboutsummaryrefslogtreecommitdiffstats
path: root/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
diff options
context:
space:
mode:
authorAdam Domurad <[email protected]>2013-02-13 11:50:12 -0500
committerAdam Domurad <[email protected]>2013-02-13 11:50:12 -0500
commit54de67be9138533a6a7e47ab02d22e433cb21caf (patch)
tree6961853f22cb5744179bff13a6e155a2d542df7c /netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
parentb73ede6f96f5a668454e31c2956eec83cfbeb873 (diff)
Fix PR580: http://www.horaoficial.cl/ loads improperly.
Diffstat (limited to 'netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java')
-rw-r--r--netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java93
1 files changed, 62 insertions, 31 deletions
diff --git a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
index 26e0b5d..73de95f 100644
--- a/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
+++ b/netx/net/sourceforge/jnlp/runtime/JNLPClassLoader.java
@@ -17,6 +17,10 @@ package net.sourceforge.jnlp.runtime;
import static net.sourceforge.jnlp.runtime.Translator.R;
+import java.util.concurrent.locks.ReentrantLock;
+
+import java.util.concurrent.locks.Lock;
+
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
@@ -114,9 +118,12 @@ public class JNLPClassLoader extends URLClassLoader {
/** True if the application has a signed JNLP File */
private boolean isSignedJNLP = false;
- /** map from JNLPFile url to shared classloader */
- private static Map<String, JNLPClassLoader> urlToLoader =
- new HashMap<String, JNLPClassLoader>(); // never garbage collected!
+ /** map from JNLPFile unique key to shared classloader */
+ private static Map<String, JNLPClassLoader> uniqueKeyToLoader = new ConcurrentHashMap<String, JNLPClassLoader>();
+
+ /** map from JNLPFile unique key to lock, the lock is needed to enforce correct
+ * initialization of applets that share a unique key*/
+ private static Map<String, ReentrantLock> uniqueKeyToLock = new HashMap<String, ReentrantLock>();
/** the directory for native code */
private File nativeDir = null; // if set, some native code exists
@@ -338,6 +345,26 @@ public class JNLPClassLoader extends URLClassLoader {
}
/**
+ * Gets the lock for a given unique key, creating one if it does not yet exist.
+ * This operation is atomic & thread-safe.
+ *
+ * @param file the file whose unique key should be used
+ * @return the lock
+ */
+ private static ReentrantLock getUniqueKeyLock(String uniqueKey) {
+ synchronized (uniqueKeyToLock) {
+ ReentrantLock storedLock = uniqueKeyToLock.get(uniqueKey);
+
+ if (storedLock == null) {
+ storedLock = new ReentrantLock();
+ uniqueKeyToLock.put(uniqueKey, storedLock);
+ }
+
+ return storedLock;
+ }
+ }
+
+ /**
* Returns a JNLP classloader for the specified JNLP file.
*
* @param file the file to load classes for
@@ -359,11 +386,8 @@ public class JNLPClassLoader extends URLClassLoader {
JNLPClassLoader loader = null;
String uniqueKey = file.getUniqueKey();
- if (uniqueKey != null)
- baseLoader = urlToLoader.get(uniqueKey);
-
- try {
-
+ synchronized ( getUniqueKeyLock(uniqueKey) ) {
+ baseLoader = uniqueKeyToLoader.get(uniqueKey);
// A null baseloader implies that no loader has been created
// for this codebase/jnlp yet. Create one.
@@ -375,7 +399,7 @@ public class JNLPClassLoader extends URLClassLoader {
// New loader init may have caused extentions to create a
// loader for this unique key. Check.
- JNLPClassLoader extLoader = urlToLoader.get(uniqueKey);
+ JNLPClassLoader extLoader = uniqueKeyToLoader.get(uniqueKey);
if (extLoader != null && extLoader != loader) {
if (loader.signing && !extLoader.signing)
@@ -404,16 +428,12 @@ public class JNLPClassLoader extends URLClassLoader {
loader = baseLoader;
}
- } catch (LaunchException e) {
- throw e;
- }
+ // loaders are mapped to a unique key. Only extensions and parent
+ // share a key, so it is safe to always share based on it
- // loaders are mapped to a unique key. Only extensions and parent
- // share a key, so it is safe to always share based on it
-
- loader.incrementLoaderUseCount();
- synchronized(urlToLoader) {
- urlToLoader.put(uniqueKey, loader);
+ loader.incrementLoaderUseCount();
+
+ uniqueKeyToLoader.put(uniqueKey, loader);
}
return loader;
@@ -430,12 +450,17 @@ public class JNLPClassLoader extends URLClassLoader {
*/
public static JNLPClassLoader getInstance(URL location, String uniqueKey, Version version, UpdatePolicy policy, String mainName)
throws IOException, ParseException, LaunchException {
- JNLPClassLoader loader = urlToLoader.get(uniqueKey);
- if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) {
- JNLPFile jnlpFile = new JNLPFile(location, uniqueKey, version, false, policy);
+ JNLPClassLoader loader;
- loader = getInstance(jnlpFile, policy, mainName);
+ synchronized ( getUniqueKeyLock(uniqueKey) ) {
+ loader = uniqueKeyToLoader.get(uniqueKey);
+
+ if (loader == null || !location.equals(loader.getJNLPFile().getFileLocation())) {
+ JNLPFile jnlpFile = new JNLPFile(location, uniqueKey, version, false, policy);
+
+ loader = getInstance(jnlpFile, policy, mainName);
+ }
}
return loader;
@@ -2079,13 +2104,16 @@ public class JNLPClassLoader extends URLClassLoader {
*
* @throws SecurityException if caller is not trusted
*/
- private synchronized void incrementLoaderUseCount() {
-
+ private void incrementLoaderUseCount() {
+
// For use by trusted code only
if (System.getSecurityManager() != null)
System.getSecurityManager().checkPermission(new AllPermission());
-
- useCount++;
+
+ // NB: There will only ever be one class-loader per unique-key
+ synchronized ( getUniqueKeyLock(file.getUniqueKey()) ){
+ useCount++;
+ }
}
/**
@@ -2197,17 +2225,20 @@ public class JNLPClassLoader extends URLClassLoader {
*
* @throws SecurityException if caller is not trusted
*/
- public synchronized void decrementLoaderUseCount() {
+ public void decrementLoaderUseCount() {
// For use by trusted code only
if (System.getSecurityManager() != null)
System.getSecurityManager().checkPermission(new AllPermission());
- useCount--;
+ String uniqueKey = file.getUniqueKey();
+
+ // NB: There will only ever be one class-loader per unique-key
+ synchronized ( getUniqueKeyLock(uniqueKey) ) {
+ useCount--;
- if (useCount <= 0) {
- synchronized(urlToLoader) {
- urlToLoader.remove(file.getUniqueKey());
+ if (useCount <= 0) {
+ uniqueKeyToLoader.remove(uniqueKey);
}
}
}