urlclassloader.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,066 行 · 第 1/3 页
JAVA
1,066 行
{
Attributes attr = manifest.getMainAttributes();
String specTitle =
attr.getValue(Attributes.Name.SPECIFICATION_TITLE);
String specVersion =
attr.getValue(Attributes.Name.SPECIFICATION_VERSION);
String specVendor =
attr.getValue(Attributes.Name.SPECIFICATION_VENDOR);
String implTitle =
attr.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
String implVersion =
attr.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
String implVendor =
attr.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
// Look if the Manifest indicates that this package is sealed
// XXX - most likely not completely correct!
// Shouldn't we also check the sealed attribute of the complete jar?
// http://java.sun.com/products/jdk/1.4/docs/guide/extensions/spec.html#bundled
// But how do we get that jar manifest here?
String sealed = attr.getValue(Attributes.Name.SEALED);
if ("false".equals(sealed))
{
// make sure that the URL is null so the package is not sealed
url = null;
}
return definePackage(name, specTitle, specVersion, specVendor,
implTitle, implVersion, implVendor, url);
}
/**
* Finds (the first) class by name from one of the locations. The locations
* are searched in the order they were added to the URLClassLoader.
*
* @param className the classname to find
* @exception ClassNotFoundException when the class could not be found or
* loaded
* @return a Class object representing the found class
*/
protected Class findClass(final String className)
throws ClassNotFoundException
{
// Just try to find the resource by the (almost) same name
String resourceName = className.replace('.', '/') + ".class";
Resource resource = findURLResource(resourceName);
if (resource == null)
throw new ClassNotFoundException(className + " not found in " + urls);
// Try to read the class data, create the CodeSource, Package and
// construct the class (and watch out for those nasty IOExceptions)
try
{
byte [] data;
InputStream in = resource.getInputStream();
int length = resource.getLength();
if (length != -1)
{
// We know the length of the data.
// Just try to read it in all at once
data = new byte[length];
int pos = 0;
while(length - pos > 0)
{
int len = in.read(data, pos, length - pos);
if (len == -1)
throw new EOFException("Not enough data reading from: "
+ in);
pos += len;
}
}
else
{
// We don't know the data length.
// Have to read it in chunks.
ByteArrayOutputStream out = new ByteArrayOutputStream(4096);
byte b[] = new byte[4096];
int l = 0;
while (l != -1)
{
l = in.read(b);
if (l != -1)
out.write(b, 0, l);
}
data = out.toByteArray();
}
final byte[] classData = data;
// Now get the CodeSource
final CodeSource source = resource.getCodeSource();
// Find out package name
String packageName = null;
int lastDot = className.lastIndexOf('.');
if (lastDot != -1)
packageName = className.substring(0, lastDot);
if (packageName != null && getPackage(packageName) == null)
{
// define the package
Manifest manifest = resource.loader.getManifest();
if (manifest == null)
definePackage(packageName,
null, null, null, null, null, null, null);
else
definePackage(packageName, manifest, resource.loader.baseURL);
}
// And finally construct the class!
SecurityManager sm = System.getSecurityManager();
if (sm != null && securityContext != null)
{
return (Class)AccessController.doPrivileged
(new PrivilegedAction()
{
public Object run()
{
return defineClass(className, classData,
0, classData.length,
source);
}
}, securityContext);
}
else
return defineClass(className, classData,
0, classData.length,
source);
}
catch (IOException ioe)
{
throw new ClassNotFoundException(className, ioe);
}
}
/**
* Finds the first occurrence of a resource that can be found. The locations
* are searched in the order they were added to the URLClassLoader.
*
* @param resourceName the resource name to look for
* @return the URLResource for the resource if found, null otherwise
*/
private Resource findURLResource(String resourceName)
{
int max = urls.size();
for (int i = 0; i < max; i++)
{
URLLoader loader = (URLLoader)urlinfos.elementAt(i);
if (loader == null)
continue;
Resource resource = loader.getResource(resourceName);
if (resource != null)
return resource;
}
return null;
}
/**
* Finds the first occurrence of a resource that can be found.
*
* @param resourceName the resource name to look for
* @return the URL if found, null otherwise
*/
public URL findResource(String resourceName)
{
Resource resource = findURLResource(resourceName);
if (resource != null)
return resource.getURL();
// Resource not found
return null;
}
/**
* If the URLStreamHandlerFactory has been set this return the appropriate
* URLStreamHandler for the given protocol, if not set returns null.
*
* @param protocol the protocol for which we need a URLStreamHandler
* @return the appropriate URLStreamHandler or null
*/
URLStreamHandler getURLStreamHandler(String protocol)
{
if (factory == null)
return null;
URLStreamHandler handler;
synchronized (factoryCache)
{
// check if there're handler for the same protocol in cache
HashMap cache = (HashMap)factoryCache.get(factory);
handler = (URLStreamHandler)cache.get(protocol);
if(handler == null)
{
// add it to cache
handler = factory.createURLStreamHandler(protocol);
cache.put(protocol, handler);
}
}
return handler;
}
/**
* Finds all the resources with a particular name from all the locations.
*
* @exception IOException when an error occurs accessing one of the
* locations
* @param resourceName the name of the resource to lookup
* @return a (possible empty) enumeration of URLs where the resource can be
* found
*/
public Enumeration findResources(String resourceName) throws IOException
{
Vector resources = new Vector();
int max = urls.size();
for (int i = 0; i < max; i++)
{
URLLoader loader = (URLLoader)urlinfos.elementAt(i);
Resource resource = loader.getResource(resourceName);
if (resource != null)
resources.add(resource.getURL());
}
return resources.elements();
}
/**
* Returns the permissions needed to access a particular code
* source. These permissions includes those returned by
* <code>SecureClassLoader.getPermissions()</code> and the actual
* permissions to access the objects referenced by the URL of the
* code source. The extra permissions added depend on the protocol
* and file portion of the URL in the code source. If the URL has
* the "file" protocol ends with a '/' character then it must be a
* directory and a file Permission to read everything in that
* directory and all subdirectories is added. If the URL had the
* "file" protocol and doesn't end with a '/' character then it must
* be a normal file and a file permission to read that file is
* added. If the <code>URL</code> has any other protocol then a
* socket permission to connect and accept connections from the host
* portion of the URL is added.
*
* @param source The codesource that needs the permissions to be accessed
* @return the collection of permissions needed to access the code resource
* @see java.security.SecureClassLoader#getPermissions()
*/
protected PermissionCollection getPermissions(CodeSource source)
{
// XXX - This implementation does exactly as the Javadoc describes.
// But maybe we should/could use URLConnection.getPermissions()?
// First get the permissions that would normally be granted
PermissionCollection permissions = super.getPermissions(source);
// Now add the any extra permissions depending on the URL location
URL url = source.getLocation();
String protocol = url.getProtocol();
if (protocol.equals("file"))
{
String file = url.getFile();
// If the file end in / it must be an directory
if (file.endsWith("/") || file.endsWith(File.separator))
{
// Grant permission to read everything in that directory and
// all subdirectories
permissions.add(new FilePermission(file + "-", "read"));
}
else
{
// It is a 'normal' file
// Grant permission to access that file
permissions.add(new FilePermission(file, "read"));
}
}
else
{
// Grant permission to connect to and accept connections from host
String host = url.getHost();
if (host != null)
permissions.add(new SocketPermission(host, "connect,accept"));
}
return permissions;
}
/**
* Returns all the locations that this class loader currently uses the
* resolve classes and resource. This includes both the initially supplied
* URLs as any URLs added later by the loader.
* @return All the currently used URLs
*/
public URL[] getURLs()
{
return (URL[]) urls.toArray(new URL[urls.size()]);
}
/**
* Creates a new instance of a <code>URLClassLoader</code> that gets
* classes from the supplied <code>URL</code>s. This class loader
* will have as parent the standard system class loader.
*
* @param urls the initial URLs used to resolve classes and
* resources
*
* @exception SecurityException when the calling code does not have
* permission to access the given <code>URL</code>s
*/
public static URLClassLoader newInstance(URL urls[])
throws SecurityException
{
return newInstance(urls, null);
}
/**
* Creates a new instance of a <code>URLClassLoader</code> that gets
* classes from the supplied <code>URL</code>s and with the supplied
* loader as parent class loader.
*
* @param urls the initial URLs used to resolve classes and
* resources
* @param parent the parent class loader
*
* @exception SecurityException when the calling code does not have
* permission to access the given <code>URL</code>s
*/
public static URLClassLoader newInstance(URL urls[],
final ClassLoader parent)
throws SecurityException
{
SecurityManager sm = System.getSecurityManager();
if (sm == null)
return new URLClassLoader(urls, parent);
else
{
final Object securityContext = sm.getSecurityContext();
// XXX - What to do with anything else then an AccessControlContext?
if (!(securityContext instanceof AccessControlContext))
throw new SecurityException
("securityContext must be AccessControlContext: "
+ securityContext);
URLClassLoader loader =
(URLClassLoader)AccessController.doPrivileged(new PrivilegedAction()
{
public Object run()
{
return new URLClassLoader
(parent, (AccessControlContext)securityContext);
}
});
loader.addURLs(urls);
return loader;
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?