Author: andygumbrecht
Date: Tue Aug 9 13:01:15 2011
New Revision: 1155344
URL: http://svn.apache.org/viewvc?rev=1155344&view=rev
Log:
Fix/improve clearSunJarFileFactoryCacheImpl - Because the internal maps are not
stable generics cannot be used.
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
URL:
http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java?rev=1155344&r1=1155343&r2=1155344&view=diff
==============================================================================
---
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
(original)
+++
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/ClassLoaderUtil.java
Tue Aug 9 13:01:15 2011
@@ -19,7 +19,6 @@ package org.apache.openejb;
import org.apache.openejb.core.TempClassLoader;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
-import org.apache.openejb.util.URLs;
import org.apache.openejb.util.UrlCache;
import java.beans.Introspector;
@@ -29,13 +28,12 @@ import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
-import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;
-import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
/**
* @version $Revision$ $Date$
@@ -45,7 +43,7 @@ public class ClassLoaderUtil {
private static final Logger logger =
Logger.getInstance(LogCategory.OPENEJB, ClassLoaderUtil.class);
private static final Map<String, List<ClassLoader>> classLoadersByApp =
new HashMap<String, List<ClassLoader>>();
private static final Map<ClassLoader, Set<String>> appsByClassLoader = new
HashMap<ClassLoader, Set<String>>();
- private static final UrlCache urlCache = new UrlCache();
+ private static final UrlCache localUrlCache = new UrlCache();
public static ClassLoader getContextClassLoader() {
return AccessController.doPrivileged(new
PrivilegedAction<ClassLoader>() {
@@ -58,15 +56,15 @@ public class ClassLoaderUtil {
}
public static File getUrlCachedName(String appId, URL url) {
- return urlCache.getUrlCachedName(appId, url);
+ return localUrlCache.getUrlCachedName(appId, url);
}
public static boolean isUrlCached(String appId, URL url) {
- return urlCache.isUrlCached(appId, url);
+ return localUrlCache.isUrlCached(appId, url);
}
public static URLClassLoader createClassLoader(String appId, URL[] urls,
ClassLoader parent) {
- urls = urlCache.cacheUrls(appId, urls);
+ urls = localUrlCache.cacheUrls(appId, urls);
URLClassLoader classLoader = new URLClassLoader(urls, parent);
List<ClassLoader> classLoaders = classLoadersByApp.get(appId);
@@ -264,7 +262,7 @@ public class ClassLoaderUtil {
}
}
- urlCache.releaseUrls(appId);
+ localUrlCache.releaseUrls(appId);
clearSunJarFileFactoryCache(appId);
}
@@ -308,111 +306,95 @@ public class ClassLoaderUtil {
* @param jarLocation String
* @param attempt int
*/
- private static void clearSunJarFileFactoryCacheImpl(final String
jarLocation, final int attempt) {
+ @SuppressWarnings({"unchecked"})
+ private static synchronized void clearSunJarFileFactoryCacheImpl(final
String jarLocation, final int attempt) {
logger.debug("Clearing Sun JarFileFactory cache for directory " +
jarLocation);
try {
final Class jarFileFactory =
Class.forName("sun.net.www.protocol.jar.JarFileFactory");
- synchronized (jarFileFactory) {
+ //Do not generify these maps as their contents are NOT stable
across runtimes.
+ final Field fileCacheField =
jarFileFactory.getDeclaredField("fileCache");
+ fileCacheField.setAccessible(true);
+ final Map fileCache = (Map) fileCacheField.get(null);
+ final Map fileCacheCopy = new HashMap(fileCache);
+
+ final Field urlCacheField =
jarFileFactory.getDeclaredField("urlCache");
+ urlCacheField.setAccessible(true);
+ final Map urlCache = (Map) urlCacheField.get(null);
+ final Map urlCacheCopy = new HashMap(urlCache);
+
+ //The only stable item we have here is the JarFile/ZipFile in this
map
+ Iterator iterator = urlCacheCopy.entrySet().iterator();
+ final List urlCacheRemoveKeys = new ArrayList();
+
+ while (iterator.hasNext()) {
+ final Map.Entry entry = (Map.Entry) iterator.next();
+ final Object key = entry.getKey();
+
+ if (key instanceof ZipFile) {
+ final ZipFile zf = (ZipFile) key;
+ final File file = new File(zf.getName()); //getName
returns File.getPath()
+ if (isParent(jarLocation, file)) {
+ //Flag for removal
+ urlCacheRemoveKeys.add(key);
+ }
+ } else {
+ logger.warning("Unexpected key type: " + key);
+ }
+ }
- Field fileCacheField =
jarFileFactory.getDeclaredField("fileCache");
+ iterator = fileCacheCopy.entrySet().iterator();
+ final List fileCacheRemoveKeys = new ArrayList();
- fileCacheField.setAccessible(true);
- Map fileCache = (Map) fileCacheField.get(null);
+ while (iterator.hasNext()) {
+ final Map.Entry entry = (Map.Entry) iterator.next();
+ final Object value = entry.getValue();
- Field urlCacheField =
jarFileFactory.getDeclaredField("urlCache");
- urlCacheField.setAccessible(true);
- Map ucf = (Map) urlCacheField.get(null);
-
- List<URL> urls = new ArrayList<URL>();
- File file;
- URL url;
-
- final Set keys = new HashSet(fileCache.keySet());
- for (final Object item : keys) {
-
- //Due to several different implementation changes in
various JDK releases
- //the 'item' can be one of the following (so far):
- //1. A URL that points to a file.
- //2. An ASCII String URI that points to a file
- //3. A String that is used as a key to a JarFile
-
- url = null;
-
- if (item instanceof URL) {
- url = (URL) item;
- } else if (item instanceof String) {
-
- JarFile jf = (JarFile) fileCache.get(item);
-
- if (null != jf) {
- url = (URL) ucf.get(jf);
- jf.close();
- } else {
- //This may now also be a plain ASCII URI in later
JDKs
- try {
- url = new URI((String) item).toURL();
- } catch (Exception e) {
- logger.warning("Don't know how to handle
object: " + item.toString() + " of type: " + item.getClass().getCanonicalName()
+ " from Sun JarFileFactory cache, skipping");
- continue;
- }
- }
-
- } else {
- logger.warning("Don't know how to handle object: " +
item.toString() + " of type: " + item.getClass().getCanonicalName() + " in Sun
JarFileFactory cache, skipping");
- continue;
- }
-
- file = null;
- try {
- file = URLs.toFile(url);
- } catch (IllegalArgumentException e) {
- //unknown kind of url
- return;
- }
+ if (urlCacheRemoveKeys.contains(value)) {
+ fileCacheRemoveKeys.add(entry.getKey());
+ }
+ }
- if (null != file && null != url && isParent(jarLocation,
file)) {
- urls.add(url);
+ //Use these unstable values as the keys for the fileCache values.
+ iterator = fileCacheRemoveKeys.iterator();
+ while (iterator.hasNext()) {
+
+ final Object next = iterator.next();
+
+ try {
+ final Object remove = fileCache.remove(next);
+ if (null != remove) {
+ logger.debug("Removed item from fileCache: " + remove);
}
+ } catch (Throwable e) {
+ logger.warning("Failed to remove item from fileCache: " +
next);
}
+ }
- JarFile jarFile;
- String key;
- for (final URL jar : urls) {
-
- //Fudge together a sun.net.www.protocol.jar.JarFileFactory
compatible key option...
- key = ("file:///" + new
File(URI.create(jar.toString())).getAbsolutePath().replace('\\', '/'));
- jarFile = (JarFile) fileCache.remove(key);
-
- if (jarFile == null) {
-
- //Try next known option...
- key = jar.toExternalForm();
- jarFile = (JarFile) fileCache.remove(key);
-
- if (jarFile == null) {
-
- //Try next known option...
- jarFile = (JarFile) fileCache.remove(jar);
-
- if (jarFile == null) {
- //To be continued...
- //If you find another 'fileCache.remove(?)'
option then add it here.
- continue;
- }
- }
- }
+ iterator = urlCacheRemoveKeys.iterator();
+ while (iterator.hasNext()) {
+
+ final Object next = iterator.next();
- ucf.remove(jarFile);
+ try {
+ final Object remove = urlCache.remove(next);
try {
- jarFile.close();
+ ((ZipFile) next).close();
} catch (Throwable e) {
//Ignore
}
+
+ if (null != remove) {
+ logger.debug("Removed item from urlCache: " + remove);
+ }
+ } catch (Throwable e) {
+ logger.warning("Failed to remove item from urlCache: " +
next);
}
+
}
+
} catch (ConcurrentModificationException e) {
if (attempt > 0) {
clearSunJarFileFactoryCacheImpl(jarLocation, (attempt - 1));