Class PreferredClassProvider
- Direct Known Subclasses:
RequireDlPermProvider
RMIClassLoader provider that supports preferred classes.
See the RMIClassLoader specification for information about how to install and
configure the RMIClassLoader service provider.
PreferredClassProvider uses instances of PreferredClassLoader to load
classes from codebase URL paths supplied to RMIClassLoader.loadClass methods.
PreferredClassProvider does not enforce DownloadPermission by default,
but a subclass can configure it to do so by passing true as the argument to the
protected constructor.
By overriding the getClassAnnotation(ClassLoader)
method, a subclass can also configure the class annotations to be used for classes defined by the
system class loader, its ancestor class loaders, and any class loader that is not an instance of
ClassAnnotation or URLClassLoader.
Common Terms and Behaviors
The following section defines terms and describes behaviors common to howPreferredClassProvider implements the abstract methods of
RMIClassLoaderSpi. Where applicable, these definitions and descriptions are
relative to the instance of PreferredClassProvider on which a method is invoked and
the context in which it is invoked.
The annotation string for a class loader is determined by the following procedure:
- If the loader is the system class loader or an ancestor of the system class loader (including
the bootstrap class loader), the annotation string is the result of invoking
getClassAnnotation(ClassLoader)with the loader. - Otherwise, if the loader is an instance of
ClassAnnotation, the annotation string is the result of invokinggetClassAnnotationon the loader. - Otherwise, if the loader is an instance of
URLClassLoader, the annotation string is a space-separated list of the URLs returned by an invocation ofgetURLson the loader. - Otherwise, the annotation string is the result of invoking
getClassAnnotation(ClassLoader)with the loader.
URL(String) constructor; if such parsing would result in a
MalformedURLException, then the annotation URL path for the loader is only defined to the
extent that it is not equal to any other path of URLs.
A PreferredClassProvider 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
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.
The methods loadClass, loadProxyClass, and getClassLoader, which each have a String parameter named
codebase, have the following behaviors in common:
codebasemay benull. If it is notnull, it is interpreted as a path of URLs by parsing it as a list of URLs separated by spaces, where each URL is parsed as with theURL(String)constructor; this could result in aMalformedURLException. This path of URLs is the codebase URL path for the invocation.- A class loader known as the codebase loader is chosen based on
codebaseand the current thread's context class loader as follows. Ifcodebaseisnull, then the codebase loader is the current thread's context class loader. Otherwise, for each non-nullloader starting with the current thread's context class loader and continuing with each successive parent class loader, if the codebase URL path is equal to the loader's annotation URL path, then the codebase loader is that loader. If no such matching loader is found, then the codebase loader is the loader in thisPreferredClassProvider's internal table with the codebase URL path as the key's path of URLs and the current thread's context class loader as the key's parent class loader. If no such entry exists in the table, then one is created by invokingcreateClassLoaderwith the codebase URL path, the current thread's context class loader, and thebooleanrequireDlPermvalue that thisPreferredClassProviderwas constructed with; the created loader is added to the table, and it is chosen as the codebase loader. - The current security context has permission to access the codebase loader if it has
the appropriate permission for each of the URLs in the codebase loader's annotation URL path,
where the appropriate permission for a URL is defined as follows. If the result of invoking
openConnection().getPermission()on theURLobject is not aFilePermissionor if it is aFilePermissionwhose name does not contain a directory separator, then that permission is the appropriate permission. If it is aFilePermissionwhose name contains a directory separator, then the appropriate permission is aFilePermissionwith action"read"and the same name except with the last path segment replaced with"-"(that is, permission to read all files in the same directory and all subdirectories).
When PreferredClassProvider attempts to load a class (or interface) named
N using class loader L, it does so in a manner equivalent
to evaluating the following expression:
Class.forName(N, false, L)
In particular, the case of N being the binary name of an array class is
supported.- Since:
- 2.0
This implementation uses the
Loggernamednet.jini.loader.pref.PreferredClassProviderto log information at the following levels:Level Description FINEclass loading failures HANDLEDexceptions caught during class loading operations FINEinvocations of loadClassandloadProxyClassFINESTdetailed activity of loadClassandloadProxyClassimplementations - Author:
- Sun Microsystems, Inc.
-
Constructor Summary
ConstructorsModifierConstructorDescriptionCreates a newPreferredClassProvider.protectedPreferredClassProvider(boolean requireDlPerm) Creates a newPreferredClassProvider. -
Method Summary
Modifier and TypeMethodDescriptionprotected ClassLoadercreateClassLoader(URL[] urls, ClassLoader parent, boolean requireDlPerm) Creates the class loader for thisPreferredClassProviderto use to load classes from the specified path of URLs with the specified delegation parent.Provides the implementation forRMIClassLoaderSpi.getClassAnnotation(Class).protected StringgetClassAnnotation(ClassLoader loader) Returns the annotation string for the specified class loader.getClassLoader(String codebase) Provides the implementation forRMIClassLoaderSpi.getClassLoader(String).loadClass(String codebase, String name, ClassLoader defaultLoader) Provides the implementation forRMIClassLoaderSpi.loadClass(String, String, ClassLoader).loadProxyClass(String codebase, String[] interfaceNames, ClassLoader defaultLoader) Provides the implementation ofRMIClassLoaderSpi.loadProxyClass(String, String[], ClassLoader).
-
Constructor Details
-
PreferredClassProvider
public PreferredClassProvider()Creates a newPreferredClassProvider.This constructor is used by the
RMIClassLoaderservice provider location mechanism whenPreferredClassProvideris configured as theRMIClassLoaderprovider class.If there is a security manager, its
checkCreateClassLoadermethod is invoked; this could result in aSecurityException.DownloadPermissionis not enforced by the created provider.- Throws:
SecurityException- if there is a security manager and the invocation of itscheckCreateClassLoadermethod fails
-
PreferredClassProvider
protected PreferredClassProvider(boolean requireDlPerm) Creates a newPreferredClassProvider.This constructor is used by subclasses to control whether or not
DownloadPermissionis enforced.If there is a security manager, its
checkCreateClassLoadermethod is invoked; this could result in aSecurityException.- Parameters:
requireDlPerm- iftrue, the class loaders created by the provider will only define classes with aCodeSourcethat is grantedDownloadPermission- Throws:
SecurityException- if there is a security manager and the invocation of itscheckCreateClassLoadermethod fails
-
-
Method Details
-
loadClass
public Class loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException Provides the implementation forRMIClassLoaderSpi.loadClass(String, String, ClassLoader).PreferredClassProviderimplements this method as follows:If
nameis the binary name of an array class (of one or more dimensions) with a primitive element type, this method returns theClassfor that array class.Otherwise, if
defaultLoaderis notnulland any of the following conditions are true:- There is no security manager.
- The codebase loader is not the current thread's context class loader and the current security context does not have permission to access the codebase loader.
codebaseisnull.- The specified codebase URL path is equal to the annotation URL path of
defaultLoader. - The codebase loader is not an instance of
PreferredClassLoader. - The codebase loader is an instance of
PreferredClassLoaderand an invocation ofisPreferredResourceon the codebase loader with the class name described below as the first argument andtrueas the second argument returnsfalse. Ifnameis the binary name of an array class (of one or more dimensions) with a element type that is a reference type, the class name passed toisPreferredResourceis the binary name of that element type; otherwise, the class name passed toisPreferredResourceisname. This invocation is only done if none of the previous conditions are true. IfisPreferredResourcethrows anIOException, this method throws aClassNotFoundException.
defaultLoader. If this attempt succeeds, this method returns the resultingClass; if it throws aClassNotFoundException, this method proceeds as follows.Otherwise, this method attempts to load the class with the specified name using the codebase loader, if there is a security manager and the current security context has permission to access the codebase loader, or using the current thread's context class loader otherwise. If this attempt succeeds, this method returns the resulting
Class; if it throws aClassNotFoundException, this method throws aClassNotFoundException.- Specified by:
loadClassin classRMIClassLoaderSpi- Parameters:
codebase- the codebase URL path as a space-separated list of URLs, ornullname- the binary name of the class to loaddefaultLoader- additional contextual class loader to use, ornull- Returns:
- the
Classobject representing the loaded class - Throws:
MalformedURLException- ifcodebaseis non-nulland contains an invalid URLClassNotFoundException- if a definition for the class could not be loaded
-
getClassAnnotation
Provides the implementation forRMIClassLoaderSpi.getClassAnnotation(Class).PreferredClassProviderimplements this method as follows:If
clis an array class (of one or more dimensions) with a primitive element type, this method returnsnull.Otherwise, this method returns the annotation string for the defining class loader of
cl, except that if the annotation string would be determined by an invocation ofURLClassLoader.getURLson that loader and the current security context does not have the permissions necessary to connect to each URL returned by that invocation (where the permission to connect to a URL is determined by invokingopenConnection().getPermission()on theURLobject), this method returns the result of invokinggetClassAnnotation(ClassLoader)with the loader instead.- Specified by:
getClassAnnotationin classRMIClassLoaderSpi- Parameters:
cl- the class to obtain the annotation string for- Returns:
- the annotation string for the class, or
null
-
getClassAnnotation
Returns the annotation string for the specified class loader.This method is invoked in order to determine the annotation string for the system class loader, an ancestor of the system class loader, any class loader that is not an instance of
ClassAnnotationorURLClassLoader, or (for an invocation ofgetClassAnnotation(Class)) aURLClassLoaderfor which the current security context does not have the permissions necessary to connect to all of its URLs.PreferredClassProviderimplements this method as follows:This method returns the value of the system property
"java.rmi.server.codebase"(or possibly an earlier cached value).- Parameters:
loader- the class loader to obtain the annotation string for- Returns:
- the annotation string for the class loader, or
null
-
getClassLoader
Provides the implementation forRMIClassLoaderSpi.getClassLoader(String).PreferredClassProviderimplements this method as follows:If there is a security manager, its
checkPermissionmethod is invoked with aRuntimePermission("getClassLoader")permission; this could result in aSecurityException. Also, if there is a security manager, the codebase loader is not the current thread's context class loader, and the current security context does not have permission to access the codebase loader, this method throws aSecurityException.This method returns the codebase loader if there is a security manager, or the current thread's context class loader otherwise.
- Specified by:
getClassLoaderin classRMIClassLoaderSpi- Parameters:
codebase- the codebase URL path as a space-separated list of URLs, ornull- Returns:
- a class loader for the specified codebase URL path
- Throws:
MalformedURLException- ifcodebaseis non-nulland contains an invalid URLSecurityException- if there is a security manager and the invocation of itscheckPermissionmethod fails, or if the current security context does not have the permissions necessary to connect to all of the URLs in the codebase URL path
-
loadProxyClass
public Class loadProxyClass(String codebase, String[] interfaceNames, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException Provides the implementation ofRMIClassLoaderSpi.loadProxyClass(String, String[], ClassLoader).PreferredClassProviderimplements this method as follows:If
defaultLoaderis notnulland any of the following conditions are true:- There is no security manager.
- The codebase loader is not the current thread's context class loader and the current security context does not have permission to access the codebase loader.
codebaseisnull.- The specified codebase URL path is equal to the annotation URL path of
defaultLoader. - The codebase loader is not an instance of
PreferredClassLoader. - The codebase loader is an instance of
PreferredClassLoaderand an invocation ofisPreferredResourceon the codebase loader for each element ofinterfaces, with the element as the first argument andtrueas the second argument, all returnfalse. These invocations are only done if none of the previous conditions are true. If any invocation ofisPreferredResourcethrows anIOException, this method throws aClassNotFoundException.
interfacesusingdefaultLoader. If all of the interfaces are loaded successfully, then- If all of the loaded interfaces are
public: if there is a security manager, the codebase loader is the current thread's context class loader or the current security context has permission to access the codebase loader, and the annotation URL path for the codebase loader is not equal to the annotation URL path fordefaultLoader, this method first attempts to get a dynamic proxy class (usingProxy.getProxyClass) that is defined by the codebase loader and that implements all of the interfaces, and if this attempt succeeds, this method returns the resultingClass. Otherwise, this method attempts to get a dynamic proxy class that is defined bydefaultLoaderand that implements all of the interfaces. If that attempt succeeds, this method returns the resultingClass; if it throws anIllegalArgumentException, this method throws aClassNotFoundException. - If all of the non-
publicinterfaces are defined by the same class loader: this method attempts to get a dynamic proxy class that is defined by that loader and that implements all of the interfaces. If this attempt succeeds, this method returns the resultingClass; if it throws anIllegalArgumentException, this method throws aClassNotFoundException. - Otherwise (if there are two or more non-
publicinterfaces defined by different class loaders): this method throws aLinkageError.
ClassNotFoundException, this method proceeds as follows.Otherwise, this method attempts to load all of the interfaces named by the elements of
interfacesusing the codebase loader, if there is a security manager and the current security context has permission to access the codebase loader, or using the current thread's context class loader otherwise. If all of the interfaces are loaded successfully, then- If all of the loaded interfaces are
public: this method attempts to get a dynamic proxy class that is defined by the loader used to load the interfaces and that implements all of the interfaces. If this attempt succeeds, this method returns the resultingClass; if it throws anIllegalArgumentException, this method throws aClassNotFoundException. - If all of the non-
publicinterfaces are defined by the same class loader: this method attempts to get a dynamic proxy class that is defined by that loader and that implements all of the interfaces. If this attempt succeeds, this method returns the resultingClass; if it throws anIllegalArgumentException, this method throws aClassNotFoundException. - Otherwise (if there are two or more non-
publicinterfaces defined by different class loaders): this method throws aLinkageError.
ClassNotFoundException, this method throws aClassNotFoundException.- Specified by:
loadProxyClassin classRMIClassLoaderSpi- Parameters:
codebase- the codebase URL path as a space-separated list of URLs, ornullinterfaceNames- the binary names of the interfaces for the proxy class to implementdefaultLoader- additional contextual class loader to use, ornull- Returns:
- a dynamic proxy class that implements the named interfaces
- Throws:
MalformedURLException- ifcodebaseis non-nulland contains an invalid URLClassNotFoundException- if a definition for one of the named interfaces could not be loaded, or if creation of the dynamic proxy class failed (such as ifProxy.getProxyClasswould throw anIllegalArgumentExceptionfor the given interface list)
-
createClassLoader
Creates the class loader for thisPreferredClassProviderto use to load classes from the specified path of URLs with the specified delegation parent.PreferredClassProviderimplements this method as follows:This method creates a new instance of
PreferredClassLoaderthat loads classes and resources fromurls, delegates toparent, and enforcesDownloadPermissionifrequireDlPermistrue. The created loader uses a restricted security context to ensure that the URL retrieval operations undertaken by the loader cannot exercise a permission that is not implied by the permissions necessary to access the loader as a codebase loader for the specified path of URLs.- Parameters:
urls- the path of URLs to load classes and resources fromparent- the parent class loader for delegationrequireDlPerm- iftrue, the loader must only define classes with aCodeSourcethat is grantedDownloadPermission- Returns:
- the created class loader
- Since:
- 2.1
-