Author: peter_firmstone Date: Thu May 16 08:35:10 2013 New Revision: 1483245
URL: http://svn.apache.org/r1483245 Log: Create net.jini.loader.codebaseAnnotation property to allow users to choose between URL (as per previous releases) or Uri to be used keys in Map's in ClassLoader infrastructure; LoaderKey in PreferredClassProvider and CodeSource in SecureClassLoader for cached ProtectionDomain's. Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java?rev=1483245&r1=1483244&r2=1483245&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/loader/pref/PreferredClassProvider.java Thu May 16 08:35:10 2013 @@ -66,8 +66,9 @@ import org.apache.river.api.net.Uri; * service provider. * * <p><code>PreferredClassProvider</code> uses instances of {@link - * PreferredClassLoader} to load classes from codebase URL paths - * supplied to <code>RMIClassLoader.loadClass</code> methods. + * PreferredClassLoader} to load classes from codebase URI paths + * supplied to <code>RMIClassLoader.loadClass</code> methods. In + * previous releases only codebase URL paths were permitted. * * <p><code>PreferredClassProvider</code> does not enforce {@link * DownloadPermission} by default, but a subclass can configure it to @@ -127,10 +128,23 @@ import org.apache.river.api.net.Uri; * * <p>A <code>PreferredClassProvider</code> maintains an internal * table of class loader instances indexed by keys that comprise a - * path of URLs and a parent class loader. The table does not + * path of URIs and a parent class loader. In previous releases keys utilised + * {@link URL}, but now utilise {@link Uri} by default. The following property + * <code>-Dnet.jini.loader.codebaseAnnotation=URL</code> + * may be set from the command line to revert to {@link URL}. The table does not * strongly reference the class loader instances, in order to allow * them (and the classes they have defined) to be garbage collected * when they are not otherwise reachable. + * + * <p>The behavioural difference between {@link Uri} and {@link URL} when used + * in ClassLoader index keys is subtle, {@link URL} remote links rely on DNS to resolve + * domain names to IP addresses, for this reason, when using strict {@link URL} + * codebase annotations, the IP address of each codebase at the time they're resolved + * is part of the codebase annotations identity. {@link Uri} identity on the other hand is + * determined by RFC3986 normalization and is more flexible the codebase server + * to change its IP address or be replicated by other codebase servers + * different IP addresses, provided they can be reached by their domain name + * address. * * <p>The methods {@link #loadClass loadClass}, {@link #loadProxyClass * loadProxyClass}, and {@link #getClassLoader getClassLoader}, which @@ -234,6 +248,23 @@ import org.apache.river.api.net.Uri; * </table> **/ public class PreferredClassProvider extends RMIClassLoaderSpi { + + /** + * value of "net.jini.loader.codebaseAnnotation" property, as cached at class + * initialization time. It may contain malformed URLs. + */ + private final static boolean uri; + static { + String codebaseAnnotationProperty = null; + String prop = AccessController.doPrivileged( + new GetPropertyAction("net.jini.loader.codebaseAnnotation")); + if (prop != null && prop.trim().length() > 0) { + codebaseAnnotationProperty = prop; + } + if (codebaseAnnotationProperty == null) uri = true; + else if ("URL".equalsIgnoreCase(codebaseAnnotationProperty)) uri = false; + else uri = true; + } /** encodings for primitive array class element types */ private static final String PRIMITIVE_TYPES = "BCDFIJSZ"; @@ -1654,7 +1685,7 @@ public class PreferredClassProvider exte * When a child ClassLoader is collected, the LoaderKey will be removed * within the next 10ms. */ - LoaderKey key = new LoaderKey(uris, parent, null); + LoaderKey key = uri? new LoaderKey(uris, parent, null) : new LoaderKey(urls, parent, null); ClassLoader loader = loaderTable.get(key); /* @@ -1761,7 +1792,7 @@ public class PreferredClassProvider exte } /** - * Loader table key: a codebase Uri path and a weak reference to + * Loader table key: a codebase annotation and a weak reference to * a parent class loader (possibly null). The weak reference is * registered with "refQueue" so that the entry can be removed * after the loader has become unreachable. @@ -1769,7 +1800,7 @@ public class PreferredClassProvider exte * LoaderKey used to be a combination of URL path and weak reference to a * parent class loader. * - * It was updated to utilise Uri for the following reasons: + * It was updated to also allow Uri for the following reasons: * * 1. Modern environments have dynamically assigned IP addresses, Uri can provide a * level of indirection for Dynamic DNS and Dynamic IP. @@ -1787,11 +1818,11 @@ public class PreferredClassProvider exte * interacting with the protocol etc. **/ private static class LoaderKey extends WeakReference<ClassLoader> { - private final Uri[] uris; + private final Object[] uris; private final boolean nullParent; private final int hashValue; - public LoaderKey(Uri[] urls, ClassLoader parent, ReferenceQueue<ClassLoader> refQueue) { + public LoaderKey(Object[] urls, ClassLoader parent, ReferenceQueue<ClassLoader> refQueue) { super(parent, refQueue); nullParent = (parent == null); uris = urls; Modified: river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java?rev=1483245&r1=1483244&r2=1483245&view=diff ============================================================================== --- river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java (original) +++ river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java Thu May 16 08:35:10 2013 @@ -17,6 +17,7 @@ package org.apache.river.api.net; +import com.sun.jini.action.GetPropertyAction; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; @@ -72,8 +73,16 @@ import org.apache.river.impl.Messages; * loaded by this {@code URLClassLoader} are granted permission to access the * URLs contained in the URL search list. * <p> - * Unlike java.net.URLClassLoader, CodeSource equality is based on Certificate - * and RFC3986 Uri location equality, not URL.equals(). + * Unlike java.net.URLClassLoader, {@link CodeSource#equals(java.lang.Object) } + * and {@link CodeSource#hashCode() } is based on Certificate + * and RFC3986 {@link Uri#equals(java.lang.Object) } and {@link Uri#hashCode() }, + * not {@link URL#equals(java.lang.Object)}. SecureClassLoader + * uses the overridden CodeSource equality as a key to cache ProtectionDomain's. + * <p> + * The following property + * <code>-Dnet.jini.loader.codebaseAnnotation=URL</code> + * may be set from the command line to revert to {@link URL#equals(java.lang.Object) } + * and {@link URL#hashCode() }. * <p> * This allows implementors of {@link java.rmi.Remote} to do two things: * <ol> @@ -84,6 +93,23 @@ import org.apache.river.impl.Messages; * */ public class RFC3986URLClassLoader extends java.net.URLClassLoader { + + /** + * value of "net.jini.loader.codebaseAnnotation" property, as cached at class + * initialization time. It may contain malformed URLs. + */ + private final static boolean uri; + static { + String codebaseAnnotationProperty = null; + String prop = AccessController.doPrivileged( + new GetPropertyAction("net.jini.loader.codebaseAnnotation")); + if (prop != null && prop.trim().length() > 0) { + codebaseAnnotationProperty = prop; + } + if (codebaseAnnotationProperty == null) uri = true; + else if (Uri.asciiStringsUpperCaseEqual(codebaseAnnotationProperty, "URL")) uri = false; + else uri = true; + } private final List<URL> originalUrls; // Copy on Write @@ -303,7 +329,8 @@ public class RFC3986URLClassLoader exten } } } - return loader.defineClass(origName, clBuf, 0, clBuf.length, new UriCodeSource(codeSourceUrl, (Certificate[]) null, null)); + if (uri) return loader.defineClass(origName, clBuf, 0, clBuf.length, new UriCodeSource(codeSourceUrl, (Certificate[]) null, null)); + return loader.defineClass(origName, clBuf, 0, clBuf.length, new CodeSource(codeSourceUrl, (Certificate[]) null)); } URL findResource(String name) { @@ -483,7 +510,9 @@ public class RFC3986URLClassLoader exten } } } - CodeSource codeS = new UriCodeSource(codeSourceUrl, entry.getCertificates(),null); + CodeSource codeS = uri ? + new UriCodeSource(codeSourceUrl, entry.getCertificates(),null) + : new CodeSource(codeSourceUrl, entry.getCertificates()); return loader.defineClass(origName, clBuf, 0, clBuf.length, codeS); }
