public class PreferredClassProvider extends RMIClassLoaderSpi
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
.
PreferredClassProvider
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:
getClassAnnotation(ClassLoader)
with the loader.
ClassAnnotation
, the annotation string is
the result of invoking getClassAnnotation
on the
loader.
URLClassLoader
, the annotation string is a
space-separated list of the URLs returned by an invocation of getURLs
on the loader.
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:
codebase
may be null
. If it is not null
, 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 the URL(String)
constructor; this could result in a MalformedURLException
. This path of URLs is the codebase URL path for the invocation.
codebase
and the current thread's context class loader as follows. If codebase
is
null
, then the codebase loader is the current thread's context class loader.
Otherwise, for each non-null
loader 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 this
PreferredClassProvider
'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 invoking createClassLoader
with the codebase URL path, the current thread's context class loader, and the
boolean
requireDlPerm
value that this PreferredClassProvider
was constructed with; the created loader is added to the table, and it is chosen as the codebase
loader.
openConnection()
.getPermission()
on the URL
object is not a FilePermission
or if it is a
FilePermission
whose name does not contain a directory separator, then that
permission is the appropriate permission. If it is a FilePermission
whose name
contains a directory separator, then the appropriate permission is a FilePermission
with 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(In particular, the case ofN
, false,L
)
N
being the binary name of an array class is
supported.This implementation uses the Logger
named net.jini.loader.pref.PreferredClassProvider
to log information at the following levels:
Level | Description |
---|---|
FAILED | class loading failures |
HANDLED | exceptions caught during class loading operations |
FINE | invocations of loadClass and loadProxyClass
|
FINEST | detailed activity of loadClass and
loadProxyClass implementations
|
Modifier | Constructor and Description |
---|---|
|
PreferredClassProvider()
Creates a new
PreferredClassProvider . |
protected |
PreferredClassProvider(boolean requireDlPerm)
Creates a new
PreferredClassProvider . |
Modifier and Type | Method and Description |
---|---|
protected ClassLoader |
createClassLoader(URL[] urls,
ClassLoader parent,
boolean requireDlPerm)
Creates the class loader for this
PreferredClassProvider to use to load classes
from the specified path of URLs with the specified delegation parent. |
String |
getClassAnnotation(Class cl)
Provides the implementation for
RMIClassLoaderSpi.getClassAnnotation(Class) . |
protected String |
getClassAnnotation(ClassLoader loader)
Returns the annotation string for the specified class loader.
|
ClassLoader |
getClassLoader(String codebase)
Provides the implementation for
RMIClassLoaderSpi.getClassLoader(String) . |
Class |
loadClass(String codebase,
String name,
ClassLoader defaultLoader)
Provides the implementation for
RMIClassLoaderSpi.loadClass(String, String,
ClassLoader) . |
Class |
loadProxyClass(String codebase,
String[] interfaceNames,
ClassLoader defaultLoader)
Provides the implementation of
RMIClassLoaderSpi.loadProxyClass(String, String[],
ClassLoader) . |
public PreferredClassProvider()
PreferredClassProvider
.
This constructor is used by the RMIClassLoader
service provider location mechanism
when PreferredClassProvider
is configured as the RMIClassLoader
provider class.
If there is a security manager, its checkCreateClassLoader
method is invoked; this could result in a
SecurityException
.
DownloadPermission
is not enforced by the created provider.
SecurityException
- if there is a security manager and the invocation of its
checkCreateClassLoader
method failsprotected PreferredClassProvider(boolean requireDlPerm)
PreferredClassProvider
.
This constructor is used by subclasses to control whether or not DownloadPermission
is enforced.
If there is a security manager, its checkCreateClassLoader
method is invoked; this could result in a
SecurityException
.
requireDlPerm
- if true
, the class loaders created by the provider will
only define classes with a CodeSource
that is granted DownloadPermission
SecurityException
- if there is a security manager and the invocation of its
checkCreateClassLoader
method failspublic Class loadClass(String codebase, String name, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException
RMIClassLoaderSpi.loadClass(String, String,
ClassLoader)
.
PreferredClassProvider
implements this method as follows:
If name
is the binary name of an array class (of one or more dimensions) with
a primitive element type, this method returns the Class
for that array class.
Otherwise, if defaultLoader
is not null
and any of the following
conditions are true:
codebase
is null
.
defaultLoader
.
PreferredClassLoader
.
PreferredClassLoader
and an invocation
of isPreferredResource
on the codebase
loader with the class name described below as the first argument and true
as the
second argument returns false
. If name
is 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 to isPreferredResource
is the binary name of that element
type; otherwise, the class name passed to isPreferredResource
is
name
. This invocation is only done if none of the previous conditions are true.
If isPreferredResource
throws an IOException
, this method throws a
ClassNotFoundException
.
defaultLoader
. If this attempt succeeds, this method returns the resulting
Class
; if it throws a ClassNotFoundException
, 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 a ClassNotFoundException
, this method throws a
ClassNotFoundException
.
loadClass
in class RMIClassLoaderSpi
codebase
- the codebase URL path as a space-separated list of URLs, or
null
name
- the binary name of the class to loaddefaultLoader
- additional contextual class loader to use, or null
Class
object representing the loaded classMalformedURLException
- if codebase
is non-null
and contains
an invalid URLClassNotFoundException
- if a definition for the class could not be loadedpublic String getClassAnnotation(Class cl)
RMIClassLoaderSpi.getClassAnnotation(Class)
.
PreferredClassProvider
implements this method as follows:
If cl
is an array class (of one or more dimensions) with a primitive element
type, this method returns null
.
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 of
URLClassLoader.getURLs
on 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 invoking openConnection()
.getPermission()
on
the URL
object), this method returns the result of invoking getClassAnnotation(ClassLoader)
with the loader instead.
getClassAnnotation
in class RMIClassLoaderSpi
cl
- the class to obtain the annotation string fornull
protected String getClassAnnotation(ClassLoader 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
ClassAnnotation
or URLClassLoader
, or (for an invocation of getClassAnnotation(Class)
) a URLClassLoader
for
which the current security context does not have the permissions necessary to connect to all
of its URLs.
PreferredClassProvider
implements this method as follows:
This method returns the value of the system property "java.rmi.server.codebase"
(or possibly an earlier cached value).
loader
- the class loader to obtain the annotation string fornull
public ClassLoader getClassLoader(String codebase) throws MalformedURLException
RMIClassLoaderSpi.getClassLoader(String)
.
PreferredClassProvider
implements this method as follows:
If there is a security manager, its checkPermission
method is invoked with a
RuntimePermission("getClassLoader")
permission; this could result in a
SecurityException
. 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 a SecurityException
.
This method returns the codebase loader if there is a security manager, or the current thread's context class loader otherwise.
getClassLoader
in class RMIClassLoaderSpi
codebase
- the codebase URL path as a space-separated list of URLs, or
null
MalformedURLException
- if codebase
is non-null
and contains
an invalid URLSecurityException
- if there is a security manager and the invocation of its
checkPermission
method fails, or if the current
security context does not have the permissions necessary to
connect to all of the URLs in the codebase URL pathpublic Class loadProxyClass(String codebase, String[] interfaceNames, ClassLoader defaultLoader) throws MalformedURLException, ClassNotFoundException
RMIClassLoaderSpi.loadProxyClass(String, String[],
ClassLoader)
.
PreferredClassProvider
implements this method as follows:
If defaultLoader
is not null
and any of the following conditions
are true:
codebase
is null
.
defaultLoader
.
PreferredClassLoader
.
PreferredClassLoader
and an invocation
of isPreferredResource
on the codebase
loader for each element of interfaces
, with the element as the first argument
and true
as the second argument, all return false
. These
invocations are only done if none of the previous conditions are true. If any invocation of
isPreferredResource
throws an IOException
, this method throws a
ClassNotFoundException
.
interfaces
using defaultLoader
. If all of the interfaces are
loaded successfully, then
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 for defaultLoader
, this
method first attempts to get a dynamic proxy class (using Proxy.getProxyClass
) that is defined by the codebase loader and that implements all of the
interfaces, and if this attempt succeeds, this method returns the resulting
Class
. Otherwise, this method attempts to get a dynamic proxy class that is
defined by defaultLoader
and that implements all of the interfaces. If that
attempt succeeds, this method returns the resulting Class
; if it throws an
IllegalArgumentException
, this method throws a ClassNotFoundException
.
public
interfaces 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
resulting Class
; if it throws an IllegalArgumentException
, this
method throws a ClassNotFoundException
.
public
interfaces defined by
different class loaders): this method throws a LinkageError
.
ClassNotFoundException
,
this method proceeds as follows.
Otherwise, this method attempts to load all of the interfaces named by the elements of
interfaces
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 all of the interfaces are loaded successfully,
then
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
resulting Class
; if it throws an IllegalArgumentException
, this
method throws a ClassNotFoundException
.
public
interfaces 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
resulting Class
; if it throws an IllegalArgumentException
, this
method throws a ClassNotFoundException
.
public
interfaces defined by
different class loaders): this method throws a LinkageError
.
ClassNotFoundException
,
this method throws a ClassNotFoundException
.loadProxyClass
in class RMIClassLoaderSpi
codebase
- the codebase URL path as a space-separated list of URLs, or
null
interfaceNames
- the binary names of the interfaces for the proxy class to implementdefaultLoader
- additional contextual class loader to use, or null
MalformedURLException
- if codebase
is non-null
and 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 if Proxy.getProxyClass
would throw an
IllegalArgumentException
for the given interface
list)protected ClassLoader createClassLoader(URL[] urls, ClassLoader parent, boolean requireDlPerm)
PreferredClassProvider
to use to load classes
from the specified path of URLs with the specified delegation parent.
PreferredClassProvider
implements this method as follows:
This method creates a new instance of PreferredClassLoader
that loads classes and
resources from urls
, delegates to parent
, and enforces DownloadPermission
if requireDlPerm
is true
. 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.
urls
- the path of URLs to load classes and resources fromparent
- the parent class loader for delegationrequireDlPerm
- if true
, the loader must only define classes with a CodeSource
that is granted DownloadPermission
Copyright © GigaSpaces.