public final class ClassLoading extends Object
RMIClassLoaderSpi
with optional verification that the codebase URIs
used to load classes provide content integrity (see Security.verifyCodebaseIntegrity
).
Traditionally a class extending RMIClassLoaderSpi
is determined by setting
the system property "java.rmi.server.RMIClassLoaderSpi", or alternatively,
RMIClassLoaderSpi
may also be defined by RMIClassLoader
using a provider visible to the ClassLoader
returned by
ClassLoader.getSystemClassLoader()
with ServiceLoader
.
As explained in River-336 this isn't always practical for IDE's or other
frameworks. To solve River-336, ClassLoading now uses ServiceLoader
to determine a RMIClassLoaderSpi
provider, however unlike
RMIClassLoader
, by default it uses ClassLoading's ClassLoader.getResources(java.lang.String)
instance to find providers.
To define a new RMIClassLoaderSpi for River to utilize, create a file in your providers jar file called:
META-INF/services/java.rmi.server.RMIClassLoaderSpi
This file should contain a single line with the fully qualified name of your RMIClassLoaderSpi implementation.
ClassLoading will iterate through all RMIClassLoaderSpi implementations found until it finds one defined by the system property:
System.getProperty("net.jini.loader.ClassLoading.provider");
If this System property is not defined, ClassLoading will load
net.jini.loader.pref.PreferredClassProvider
, alternatively
java.rmi.server.RMIClassLoader
delegates all calls to RMIClassLoader
.
If a provider is not found, it will not be updated.
Gregg Wonderly originally reported River-336 and provided a patch
containing a new CodebaseAccessClassLoader to replace RMIClassLoader
,
later Sim Isjkes created RiverClassLoader that utilized ServiceLoader.
Both implementations contained methods identical to RMIClassLoaderSpi
,
however new implementations were required to extend new provider
implementations, creating a compatibility issue with existing implementations
extending RMIClassLoaderSpi
. For backward compatibility with existing
implementations, RMIClassLoaderSpi
has been retained as the provider,
avoiding the need to recompile client code. The abilities of both
implementations, to use ServiceLoader, or to define a provider using a method
call have been retained, with the restriction that implementations are to be
obtained via ServiceLoader.
Instead, all that is required for utilization of existing service provider
RMIClassLoaderSpi
implementations is to set the system property
"net.jini.loader.ClassLoading.provider".
Modifier and Type | Method and Description |
---|---|
static String |
getClassAnnotation(Class<?> cl)
Returns the annotation string (representing a location for
the class definition as a single or space delimited list of
RFC3986 compliant URI) that JERI will use to annotate the class
descriptor when marshalling objects of the given class.
|
static ClassLoader |
getClassLoader(String codebase)
Returns a class loader that loads classes from the given codebase
RFC3986 compliant URI path.
|
static RMIClassLoaderSpi |
getProvider()
The current RMIClassLoaderSpi provider in use by ClassLoading.
|
static boolean |
installNewProvider(String providerName,
ClassLoader providerLoader)
Installs a new RMIClassLoaderSpi provider with the ClassLoader
provided.
|
static Class<?> |
loadClass(String codebase,
String name,
ClassLoader defaultLoader,
boolean verifyCodebaseIntegrity,
ClassLoader verifierLoader)
Loads a class using
RMIClassLoaderSpi.loadClass(String,String,ClassLoader) ,
optionally verifying that the RFC3986 compliant
codebase URIs provide content integrity. |
static Class<?> |
loadProxyClass(String codebase,
String[] interfaceNames,
ClassLoader defaultLoader,
boolean verifyCodebaseIntegrity,
ClassLoader verifierLoader)
Loads a dynamic proxy class using
RMIClassLoaderSpi.loadProxyClass(String,String[],ClassLoader) ,
optionally verifying that the RFC3986 compliant
codebase URIs provide content integrity. |
public static RMIClassLoaderSpi getProvider()
SecurityException
- if caller doesn't have RuntimePermission "getFactory"public static boolean installNewProvider(String providerName, ClassLoader providerLoader)
providerName
- fully defined class name of the provider, if null,
a new provider instance will be determined by system properties.providerLoader
- The class loader to be used to load
provider-configuration files and provider classes, or null if the
system class loader (or, failing that, the bootstrap class loader)
is to be used.SecurityException
- if caller doesn't have RuntimePermission "getFactory"public static ClassLoader getClassLoader(String codebase) throws MalformedURLException, SecurityException
This method delegates to the
RMIClassLoaderSpi.getClassLoader(String)
method
of the provider instance, passing codebase
as the argument.
If there is a security manger, its checkPermission
method will be invoked with a
RuntimePermission("getClassLoader")
permission;
this could result in a SecurityException
.
The provider implementation of this method may also perform further
security checks to verify that the calling context has permission to
connect to all of the URIs in the codebase URI path.
codebase
- the list of URIs (space-separated) from which
the returned class loader will load classes from, or null
MalformedURLException
- if codebase
is
non-null
and contains an non RFC3986 compliant URI, or
if codebase
is null
and a provider-specific
URL used to identify the class loader is invalidSecurityException
- if there is a security manager and the
invocation of its checkPermission
method fails, or
if the caller does not have permission to connect to all of the
URIs in the codebase URI pathpublic static String getClassAnnotation(Class<?> cl)
This method delegates to the
RMIClassLoaderSpi.getClassAnnotation(Class)
method
of the provider instance, passing cl
as the argument.
cl
- the class to obtain the annotation fornull
NullPointerException
- if cl
is null
public static Class<?> loadClass(String codebase, String name, ClassLoader defaultLoader, boolean verifyCodebaseIntegrity, ClassLoader verifierLoader) throws MalformedURLException, ClassNotFoundException
RMIClassLoaderSpi.loadClass(String,String,ClassLoader)
,
optionally verifying that the RFC3986 compliant
codebase URIs provide content integrity.
If verifyCodebaseIntegrity
is true
and codebase
is not null
, then this
method invokes Security.verifyCodebaseIntegrity
with codebase
as
the first argument and verifierLoader
as the
second argument (this invocation may be skipped if a previous
invocation of this method or loadProxyClass
has already invoked
Security.verifyCodebaseIntegrity
with the same
value of codebase
and the same effective value of
verifierLoader
as arguments without it throwing an
exception). If Security.verifyCodebaseIntegrity
throws a SecurityException
, then this method
proceeds as if codebase
were null
.
If Security.verifyCodebaseIntegrity
throws any
other exception, then this method throws that exception.
This method then invokes RMIClassLoaderSpi.loadClass
with codebase
as the
first argument (or null
if in the previous step
Security.verifyCodebaseIntegrity
was invoked and
it threw a SecurityException
), name
as the second argument, and defaultLoader
as the
third argument. If RMIClassLoaderSpi.loadClass
throws a ClassNotFoundException
, then this method
throws a ClassNotFoundException
; if
RMIClassLoaderSpi.loadClass
throws any other
exception, then this method throws that exception; otherwise,
this method returns the Class
returned by
RMIClassLoaderSpi.loadClass
.
codebase
- the list of URLs (separated by spaces) to load
the class from, or null
name
- the name of the class to loaddefaultLoader
- the class loader value (possibly
null
) to pass as the defaultLoader
argument to RMIClassLoaderSpi.loadClass
verifyCodebaseIntegrity
- if true
, verify
that the RFC3986 compliant codebase URIs provide content integrityverifierLoader
- the class loader value (possibly
null
) to pass to
Security.verifyCodebaseIntegrity
, if
verifyCodebaseIntegrity
is true
Class
object representing the loaded
classMalformedURLException
- if
Security.verifyCodebaseIntegrity
or
RMIClassLoaderSpi.loadClass
throws a
MalformedURLException
ClassNotFoundException
- if
RMIClassLoaderSpi.loadClass
throws a
ClassNotFoundException
NullPointerException
- if name
is
null
public static Class<?> loadProxyClass(String codebase, String[] interfaceNames, ClassLoader defaultLoader, boolean verifyCodebaseIntegrity, ClassLoader verifierLoader) throws MalformedURLException, ClassNotFoundException
RMIClassLoaderSpi.loadProxyClass(String,String[],ClassLoader)
,
optionally verifying that the RFC3986 compliant
codebase URIs provide content integrity.
If verifyCodebaseIntegrity
is true
and codebase
is not null
, then this
method invokes Security.verifyCodebaseIntegrity
with codebase
as
the first argument and verifierLoader
as the
second argument (this invocation may be skipped if a previous
invocation of this method or loadClass
has
already invoked Security.verifyCodebaseIntegrity
with the same value of codebase
and the same
effective value of verifierLoader
as arguments
without it throwing an exception). If
Security.verifyCodebaseIntegrity
throws a
SecurityException
, then this method proceeds as if
codebase
were null
. If
Security.verifyCodebaseIntegrity
throws any other
exception, then this method throws that exception.
This method invokes RMIClassLoaderSpi.loadProxyClass(String,String[],ClassLoader)
with codebase
as
the first argument (or null
if in the previous
step Security.verifyCodebaseIntegrity
was invoked
and it threw a SecurityException
),
interfaceNames
as the second argument, and
defaultLoader
as the third argument. If
RMIClassLoaderSpi.loadProxyClass
throws a
ClassNotFoundException
, then this method throws a
ClassNotFoundException
; if
RMIClassLoaderSpi.loadProxyClass
throws any other
exception, then this method throws that exception; otherwise,
this method returns the Class
returned by
RMIClassLoaderSpi.loadProxyClass
.
codebase
- the list of URLs (separated by spaces) to load
classes from, or null
interfaceNames
- the names of the interfaces for the proxy
class to implementdefaultLoader
- the class loader value (possibly
null
) to pass as the defaultLoader
argument to RMIClassLoader.loadProxyClass
verifyCodebaseIntegrity
- if true
, verify
that the codebase URLs provide content integrityverifierLoader
- the class loader value (possibly
null
) to pass to
Security.verifyCodebaseIntegrity
, if
verifyCodebaseIntegrity
is true
Class
object representing the loaded
dynamic proxy classMalformedURLException
- if
Security.verifyCodebaseIntegrity
or
RMIClassLoaderSpi.loadProxyClass
throws a
MalformedURLException
ClassNotFoundException
- if
RMIClassLoaderSpi.loadProxyClass
throws a
ClassNotFoundException
NullPointerException
- if interfaceNames
is
null
or if any element of
interfaceNames
is null