< prev index next >
src/java.base/share/classes/jdk/internal/loader/URLClassPath.java
Print this page
8198481: Coding style cleanups for src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java
Reviewed-by: mchung, alanb
*** 41,50 ****
--- 41,51 ----
import java.security.AccessControlContext;
import java.security.AccessControlException;
import java.security.AccessController;
import java.security.CodeSigner;
import java.security.Permission;
+ import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
*** 97,127 ****
p = props.getProperty("jdk.net.URLClassPath.disableRestrictedPermissions");
DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
! /* The original search path of URLs. */
private final List<URL> path;
! /* The stack of unopened URLs */
private final Stack<URL> urls = new Stack<>();
! /* The resulting search path of Loaders */
private final ArrayList<Loader> loaders = new ArrayList<>();
! /* Map of each URL opened to its corresponding Loader */
private final HashMap<String, Loader> lmap = new HashMap<>();
! /* The jar protocol handler to use when creating new URLs */
private final URLStreamHandler jarHandler;
! /* Whether this URLClassLoader has been closed yet */
private boolean closed = false;
! /* The context to be used when loading classes and resources. If non-null
! * this is the context that was captured during the creation of the
! * URLClassLoader. null implies no additional security restrictions. */
private final AccessControlContext acc;
/**
* Creates a new URLClassPath for the given URLs. The URLs will be
* searched in the order specified for classes and resources. A URL
--- 98,131 ----
p = props.getProperty("jdk.net.URLClassPath.disableRestrictedPermissions");
DISABLE_ACC_CHECKING = p != null ? p.equals("true") || p.equals("") : false;
}
! /** The original search path of URLs. */
private final List<URL> path;
! /** The stack of unopened URLs. */
private final Stack<URL> urls = new Stack<>();
! /** The resulting search path of Loaders. */
private final ArrayList<Loader> loaders = new ArrayList<>();
! /** Map of each URL opened to its corresponding Loader. */
private final HashMap<String, Loader> lmap = new HashMap<>();
! /** The jar protocol handler to use when creating new URLs. */
private final URLStreamHandler jarHandler;
! /** Whether this URLClassLoader has been closed yet. */
private boolean closed = false;
! /**
! * The context to be used when loading classes and resources. If
! * non-null this is the context that was captured during the creation
! * of the URLClassLoader. null implies no additional security
! * restrictions.
! */
private final AccessControlContext acc;
/**
* Creates a new URLClassPath for the given URLs. The URLs will be
* searched in the order specified for classes and resources. A URL
*** 207,217 ****
List<IOException> result = new LinkedList<>();
for (Loader loader : loaders) {
try {
loader.close();
} catch (IOException e) {
! result.add (e);
}
}
closed = true;
return result;
}
--- 211,221 ----
List<IOException> result = new LinkedList<>();
for (Loader loader : loaders) {
try {
loader.close();
} catch (IOException e) {
! result.add(e);
}
}
closed = true;
return result;
}
*** 270,280 ****
* Finds the resource with the specified name on the URL search path
* or null if not found or security check fails.
*
* @param name the name of the resource
* @param check whether to perform a security check
! * @return a <code>URL</code> for the resource, or <code>null</code>
* if the resource could not be found.
*/
public URL findResource(String name, boolean check) {
Loader loader;
for (int i = 0; (loader = getLoader(i)) != null; i++) {
--- 274,284 ----
* Finds the resource with the specified name on the URL search path
* or null if not found or security check fails.
*
* @param name the name of the resource
* @param check whether to perform a security check
! * @return a {@code URL} for the resource, or {@code null}
* if the resource could not be found.
*/
public URL findResource(String name, boolean check) {
Loader loader;
for (int i = 0; (loader = getLoader(i)) != null; i++) {
*** 401,411 ****
public Enumeration<Resource> getResources(final String name) {
return getResources(name, true);
}
! /*
* Returns the Loader at the specified position in the URL search
* path. The URLs are opened and expanded as needed. Returns null
* if the specified index is out of range.
*/
private synchronized Loader getLoader(int index) {
--- 405,415 ----
public Enumeration<Resource> getResources(final String name) {
return getResources(name, true);
}
! /**
* Returns the Loader at the specified position in the URL search
* path. The URLs are opened and expanded as needed. Returns null
* if the specified index is out of range.
*/
private synchronized Loader getLoader(int index) {
*** 458,474 ****
lmap.put(urlNoFragString, loader);
}
return loaders.get(index);
}
! /*
* Returns the Loader for the specified base URL.
*/
private Loader getLoader(final URL url) throws IOException {
try {
! return java.security.AccessController.doPrivileged(
! new java.security.PrivilegedExceptionAction<>() {
public Loader run() throws IOException {
String protocol = url.getProtocol(); // lower cased in URL
String file = url.getFile();
if (file != null && file.endsWith("/")) {
if ("file".equals(protocol)) {
--- 462,478 ----
lmap.put(urlNoFragString, loader);
}
return loaders.get(index);
}
! /**
* Returns the Loader for the specified base URL.
*/
private Loader getLoader(final URL url) throws IOException {
try {
! return AccessController.doPrivileged(
! new PrivilegedExceptionAction<>() {
public Loader run() throws IOException {
String protocol = url.getProtocol(); // lower cased in URL
String file = url.getFile();
if (file != null && file.endsWith("/")) {
if ("file".equals(protocol)) {
*** 485,495 ****
} else {
return new JarLoader(url, jarHandler, lmap, acc);
}
}
}, acc);
! } catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
}
private static final JavaNetURLAccess JNUA
--- 489,499 ----
} else {
return new JarLoader(url, jarHandler, lmap, acc);
}
}
}, acc);
! } catch (PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
}
private static final JavaNetURLAccess JNUA
*** 498,521 ****
private static boolean isDefaultJarHandler(URL u) {
URLStreamHandler h = JNUA.getHandler(u);
return h instanceof sun.net.www.protocol.jar.Handler;
}
! /*
* Pushes the specified URLs onto the list of unopened URLs.
*/
private void push(URL[] us) {
synchronized (urls) {
for (int i = us.length - 1; i >= 0; --i) {
urls.push(us[i]);
}
}
}
! /*
! * Check whether the resource URL should be returned.
! * Return null on security check failure.
* Called by java.net.URLClassLoader.
*/
public static URL checkURL(URL url) {
if (url != null) {
try {
--- 502,525 ----
private static boolean isDefaultJarHandler(URL u) {
URLStreamHandler h = JNUA.getHandler(u);
return h instanceof sun.net.www.protocol.jar.Handler;
}
! /**
* Pushes the specified URLs onto the list of unopened URLs.
*/
private void push(URL[] us) {
synchronized (urls) {
for (int i = us.length - 1; i >= 0; --i) {
urls.push(us[i]);
}
}
}
! /**
! * Checks whether the resource URL should be returned.
! * Returns null on security check failure.
* Called by java.net.URLClassLoader.
*/
public static URL checkURL(URL url) {
if (url != null) {
try {
*** 525,537 ****
}
}
return url;
}
! /*
! * Check whether the resource URL should be returned.
! * Throw exception on failure.
* Called internally within this file.
*/
public static void check(URL url) throws IOException {
SecurityManager security = System.getSecurityManager();
if (security != null) {
--- 529,541 ----
}
}
return url;
}
! /**
! * Checks whether the resource URL should be returned.
! * Throws exception on failure.
* Called internally within this file.
*/
public static void check(URL url) throws IOException {
SecurityManager security = System.getSecurityManager();
if (security != null) {
*** 569,586 ****
*/
private static class Loader implements Closeable {
private final URL base;
private JarFile jarfile; // if this points to a jar file
! /*
* Creates a new Loader for the specified URL.
*/
Loader(URL url) {
base = url;
}
! /*
* Returns the base URL for this Loader.
*/
URL getBaseURL() {
return base;
}
--- 573,590 ----
*/
private static class Loader implements Closeable {
private final URL base;
private JarFile jarfile; // if this points to a jar file
! /**
* Creates a new Loader for the specified URL.
*/
Loader(URL url) {
base = url;
}
! /**
* Returns the base URL for this Loader.
*/
URL getBaseURL() {
return base;
}
*** 656,694 ****
return uc.getContentLength();
}
};
}
! /*
* Returns the Resource for the specified name, or null if not
* found or the caller does not have the permission to get the
* resource.
*/
Resource getResource(final String name) {
return getResource(name, true);
}
! /*
! * close this loader and release all resources
! * method overridden in sub-classes
*/
@Override
public void close() throws IOException {
if (jarfile != null) {
jarfile.close();
}
}
! /*
* Returns the local class path for this loader, or null if none.
*/
URL[] getClassPath() throws IOException {
return null;
}
}
! /*
* Nested class used to represent a Loader of resources from a JAR URL.
*/
static class JarLoader extends Loader {
private JarFile jar;
private final URL csu;
--- 660,698 ----
return uc.getContentLength();
}
};
}
! /**
* Returns the Resource for the specified name, or null if not
* found or the caller does not have the permission to get the
* resource.
*/
Resource getResource(final String name) {
return getResource(name, true);
}
! /**
! * Closes this loader and release all resources.
! * Method overridden in sub-classes.
*/
@Override
public void close() throws IOException {
if (jarfile != null) {
jarfile.close();
}
}
! /**
* Returns the local class path for this loader, or null if none.
*/
URL[] getClassPath() throws IOException {
return null;
}
}
! /**
* Nested class used to represent a Loader of resources from a JAR URL.
*/
static class JarLoader extends Loader {
private JarFile jar;
private final URL csu;
*** 698,708 ****
private final AccessControlContext acc;
private boolean closed = false;
private static final JavaUtilZipFileAccess zipAccess =
SharedSecrets.getJavaUtilZipFileAccess();
! /*
* Creates a new JarLoader for the specified URL referring to
* a JAR file.
*/
JarLoader(URL url, URLStreamHandler jarHandler,
HashMap<String, Loader> loaderMap,
--- 702,712 ----
private final AccessControlContext acc;
private boolean closed = false;
private static final JavaUtilZipFileAccess zipAccess =
SharedSecrets.getJavaUtilZipFileAccess();
! /**
* Creates a new JarLoader for the specified URL referring to
* a JAR file.
*/
JarLoader(URL url, URLStreamHandler jarHandler,
HashMap<String, Loader> loaderMap,
*** 738,749 ****
}
private void ensureOpen() throws IOException {
if (jar == null) {
try {
! java.security.AccessController.doPrivileged(
! new java.security.PrivilegedExceptionAction<>() {
public Void run() throws IOException {
if (DEBUG) {
System.err.println("Opening " + csu);
Thread.dumpStack();
}
--- 742,753 ----
}
private void ensureOpen() throws IOException {
if (jar == null) {
try {
! AccessController.doPrivileged(
! new PrivilegedExceptionAction<>() {
public Void run() throws IOException {
if (DEBUG) {
System.err.println("Opening " + csu);
Thread.dumpStack();
}
*** 755,765 ****
// Add all the dependent URLs to the lmap so that loaders
// will not be created for them by URLClassPath.getLoader(int)
// if the same URL occurs later on the main class path. We set
// Loader to null here to avoid creating a Loader for each
// URL until we actually need to try to load something from them.
! for(int i = 0; i < jarfiles.length; i++) {
try {
URL jarURL = new URL(csu, jarfiles[i]);
// If a non-null loader already exists, leave it alone.
String urlNoFragString = URLUtil.urlNoFragString(jarURL);
if (!lmap.containsKey(urlNoFragString)) {
--- 759,769 ----
// Add all the dependent URLs to the lmap so that loaders
// will not be created for them by URLClassPath.getLoader(int)
// if the same URL occurs later on the main class path. We set
// Loader to null here to avoid creating a Loader for each
// URL until we actually need to try to load something from them.
! for (int i = 0; i < jarfiles.length; i++) {
try {
URL jarURL = new URL(csu, jarfiles[i]);
// If a non-null loader already exists, leave it alone.
String urlNoFragString = URLUtil.urlNoFragString(jarURL);
if (!lmap.containsKey(urlNoFragString)) {
*** 771,787 ****
}
}
return null;
}
}, acc);
! } catch (java.security.PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
}
}
! /* Throws if the given jar file is does not start with the correct LOC */
static JarFile checkJar(JarFile jar) throws IOException {
if (System.getSecurityManager() != null && !DISABLE_JAR_CHECKING
&& !zipAccess.startsWithLocHeader(jar)) {
IOException x = new IOException("Invalid Jar file");
try {
--- 775,791 ----
}
}
return null;
}
}, acc);
! } catch (PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
}
}
! /** Throws if the given jar file is does not start with the correct LOC */
static JarFile checkJar(JarFile jar) throws IOException {
if (System.getSecurityManager() != null && !DISABLE_JAR_CHECKING
&& !zipAccess.startsWithLocHeader(jar)) {
IOException x = new IOException("Invalid Jar file");
try {
*** 809,819 ****
uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
JarFile jarFile = ((JarURLConnection)uc).getJarFile();
return checkJar(jarFile);
}
! /*
* Returns the index of this JarLoader if it exists.
*/
JarIndex getIndex() {
try {
ensureOpen();
--- 813,823 ----
uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
JarFile jarFile = ((JarURLConnection)uc).getJarFile();
return checkJar(jarFile);
}
! /**
* Returns the index of this JarLoader if it exists.
*/
JarIndex getIndex() {
try {
ensureOpen();
*** 821,831 ****
throw new InternalError(e);
}
return index;
}
! /*
* Creates the resource and if the check flag is set to true, checks if
* is its okay to return the resource.
*/
Resource checkResource(final String name, boolean check,
final JarEntry entry) {
--- 825,835 ----
throw new InternalError(e);
}
return index;
}
! /**
* Creates the resource and if the check flag is set to true, checks if
* is its okay to return the resource.
*/
Resource checkResource(final String name, boolean check,
final JarEntry entry) {
*** 867,903 ****
{ return entry.getCodeSigners(); };
};
}
! /*
* Returns true iff at least one resource in the jar file has the same
* package name as that of the specified resource name.
*/
boolean validIndex(final String name) {
String packageName = name;
int pos;
! if((pos = name.lastIndexOf('/')) != -1) {
packageName = name.substring(0, pos);
}
String entryName;
ZipEntry entry;
Enumeration<JarEntry> enum_ = jar.entries();
while (enum_.hasMoreElements()) {
entry = enum_.nextElement();
entryName = entry.getName();
! if((pos = entryName.lastIndexOf('/')) != -1)
entryName = entryName.substring(0, pos);
if (entryName.equals(packageName)) {
return true;
}
}
return false;
}
! /*
* Returns the URL for a resource with the specified name
*/
@Override
URL findResource(final String name, boolean check) {
Resource rsc = getResource(name, check);
--- 871,907 ----
{ return entry.getCodeSigners(); };
};
}
! /**
* Returns true iff at least one resource in the jar file has the same
* package name as that of the specified resource name.
*/
boolean validIndex(final String name) {
String packageName = name;
int pos;
! if ((pos = name.lastIndexOf('/')) != -1) {
packageName = name.substring(0, pos);
}
String entryName;
ZipEntry entry;
Enumeration<JarEntry> enum_ = jar.entries();
while (enum_.hasMoreElements()) {
entry = enum_.nextElement();
entryName = entry.getName();
! if ((pos = entryName.lastIndexOf('/')) != -1)
entryName = entryName.substring(0, pos);
if (entryName.equals(packageName)) {
return true;
}
}
return false;
}
! /**
* Returns the URL for a resource with the specified name
*/
@Override
URL findResource(final String name, boolean check) {
Resource rsc = getResource(name, check);
*** 905,915 ****
return rsc.getURL();
}
return null;
}
! /*
* Returns the JAR Resource for the specified name.
*/
@Override
Resource getResource(final String name, boolean check) {
try {
--- 909,919 ----
return rsc.getURL();
}
return null;
}
! /**
* Returns the JAR Resource for the specified name.
*/
@Override
Resource getResource(final String name, boolean check) {
try {
*** 926,941 ****
HashSet<String> visited = new HashSet<>();
return getResource(name, check, visited);
}
! /*
* Version of getResource() that tracks the jar files that have been
* visited by linking through the index files. This helper method uses
* a HashSet to store the URLs of jar files that have been searched and
* uses it to avoid going into an infinite loop, looking for a
! * non-existent resource
*/
Resource getResource(final String name, boolean check,
Set<String> visited) {
Resource res;
String[] jarFiles;
--- 930,945 ----
HashSet<String> visited = new HashSet<>();
return getResource(name, check, visited);
}
! /**
* Version of getResource() that tracks the jar files that have been
* visited by linking through the index files. This helper method uses
* a HashSet to store the URLs of jar files that have been searched and
* uses it to avoid going into an infinite loop, looking for a
! * non-existent resource.
*/
Resource getResource(final String name, boolean check,
Set<String> visited) {
Resource res;
String[] jarFiles;
*** 943,960 ****
LinkedList<String> jarFilesList = null;
/* If there no jar files in the index that can potential contain
* this resource then return immediately.
*/
! if((jarFilesList = index.get(name)) == null)
return null;
do {
int size = jarFilesList.size();
jarFiles = jarFilesList.toArray(new String[size]);
/* loop through the mapped jar file list */
! while(count < size) {
String jarName = jarFiles[count++];
JarLoader newLoader;
final URL url;
try{
--- 947,964 ----
LinkedList<String> jarFilesList = null;
/* If there no jar files in the index that can potential contain
* this resource then return immediately.
*/
! if ((jarFilesList = index.get(name)) == null)
return null;
do {
int size = jarFilesList.size();
jarFiles = jarFilesList.toArray(new String[size]);
/* loop through the mapped jar file list */
! while (count < size) {
String jarName = jarFiles[count++];
JarLoader newLoader;
final URL url;
try{
*** 975,994 ****
/* this newly opened jar file has its own index,
* merge it into the parent's index, taking into
* account the relative path.
*/
JarIndex newIndex = newLoader.getIndex();
! if(newIndex != null) {
int pos = jarName.lastIndexOf('/');
newIndex.merge(this.index, (pos == -1 ?
null : jarName.substring(0, pos + 1)));
}
/* put it in the global hashtable */
lmap.put(urlNoFragString, newLoader);
}
! } catch (java.security.PrivilegedActionException pae) {
continue;
} catch (MalformedURLException e) {
continue;
}
--- 979,998 ----
/* this newly opened jar file has its own index,
* merge it into the parent's index, taking into
* account the relative path.
*/
JarIndex newIndex = newLoader.getIndex();
! if (newIndex != null) {
int pos = jarName.lastIndexOf('/');
newIndex.merge(this.index, (pos == -1 ?
null : jarName.substring(0, pos + 1)));
}
/* put it in the global hashtable */
lmap.put(urlNoFragString, newLoader);
}
! } catch (PrivilegedActionException pae) {
continue;
} catch (MalformedURLException e) {
continue;
}
*** 1027,1052 ****
continue;
}
/* Process the index of the new loader
*/
! if((res = newLoader.getResource(name, check, visited))
!= null) {
return res;
}
}
// Get the list of jar files again as the list could have grown
// due to merging of index files.
jarFilesList = index.get(name);
// If the count is unchanged, we are done.
! } while(count < jarFilesList.size());
return null;
}
! /*
* Returns the JAR file local class path, or null if none.
*/
@Override
URL[] getClassPath() throws IOException {
if (index != null) {
--- 1031,1056 ----
continue;
}
/* Process the index of the new loader
*/
! if ((res = newLoader.getResource(name, check, visited))
!= null) {
return res;
}
}
// Get the list of jar files again as the list could have grown
// due to merging of index files.
jarFilesList = index.get(name);
// If the count is unchanged, we are done.
! } while (count < jarFilesList.size());
return null;
}
! /**
* Returns the JAR file local class path, or null if none.
*/
@Override
URL[] getClassPath() throws IOException {
if (index != null) {
*** 1069,1079 ****
}
}
return null;
}
! /*
* Parses value of the Class-Path manifest attribute and returns
* an array of URLs relative to the specified base URL.
*/
private static URL[] parseClassPath(URL base, String value)
throws MalformedURLException
--- 1073,1083 ----
}
}
return null;
}
! /**
* Parses value of the Class-Path manifest attribute and returns
* an array of URLs relative to the specified base URL.
*/
private static URL[] parseClassPath(URL base, String value)
throws MalformedURLException
*** 1088,1103 ****
}
return urls;
}
}
! /*
* Nested class used to represent a loader of classes and resources
* from a file URL that refers to a directory.
*/
private static class FileLoader extends Loader {
! /* Canonicalized File */
private File dir;
FileLoader(URL url) throws IOException {
super(url);
if (!"file".equals(url.getProtocol())) {
--- 1092,1107 ----
}
return urls;
}
}
! /**
* Nested class used to represent a loader of classes and resources
* from a file URL that refers to a directory.
*/
private static class FileLoader extends Loader {
! /** Canonicalized File */
private File dir;
FileLoader(URL url) throws IOException {
super(url);
if (!"file".equals(url.getProtocol())) {
*** 1106,1116 ****
String path = url.getFile().replace('/', File.separatorChar);
path = ParseUtil.decode(path);
dir = (new File(path)).getCanonicalFile();
}
! /*
* Returns the URL for a resource with the specified name
*/
@Override
URL findResource(final String name, boolean check) {
Resource rsc = getResource(name, check);
--- 1110,1120 ----
String path = url.getFile().replace('/', File.separatorChar);
path = ParseUtil.decode(path);
dir = (new File(path)).getCanonicalFile();
}
! /**
* Returns the URL for a resource with the specified name
*/
@Override
URL findResource(final String name, boolean check) {
Resource rsc = getResource(name, check);
< prev index next >