Author: markt Date: Thu Oct 5 19:02:06 2017 New Revision: 1811229 URL: http://svn.apache.org/viewvc?rev=1811229&view=rev Log: Start to improved Java 9 JAR scanning Make StandardJarScanner easier to extend
Modified: tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java Modified: tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java URL: http://svn.apache.org/viewvc/tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java?rev=1811229&r1=1811228&r2=1811229&view=diff ============================================================================== --- tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java (original) +++ tomcat/tc8.5.x/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java Thu Oct 5 19:02:06 2017 @@ -26,7 +26,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.Deque; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedList; import java.util.Set; import java.util.jar.Attributes; @@ -43,6 +42,7 @@ import org.apache.tomcat.JarScanner; import org.apache.tomcat.JarScannerCallback; import org.apache.tomcat.util.ExceptionUtils; import org.apache.tomcat.util.buf.UriUtil; +import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.res.StringManager; /** @@ -176,9 +176,7 @@ public class StandardJarScanner implemen // Scan WEB-INF/lib Set<String> dirList = context.getResourcePaths(Constants.WEB_INF_LIB); if (dirList != null) { - Iterator<String> it = dirList.iterator(); - while (it.hasNext()) { - String path = it.next(); + for (String path : dirList) { if (path.endsWith(Constants.JAR_EXT) && getJarScanFilter().check(scanType, path.substring(path.lastIndexOf('/')+1))) { @@ -228,76 +226,106 @@ public class StandardJarScanner implemen // Scan the classpath if (isScanClassPath()) { - if (log.isTraceEnabled()) { - log.trace(sm.getString("jarScan.classloaderStart")); - } + doScanClassPath(scanType, context, callback, processedURLs); + } + } - ClassLoader stopLoader = null; - if (!isScanBootstrapClassPath()) { - // Stop when we reach the bootstrap class loader - stopLoader = ClassLoader.getSystemClassLoader().getParent(); - } - ClassLoader classLoader = context.getClassLoader(); + protected void doScanClassPath(JarScanType scanType, ServletContext context, + JarScannerCallback callback, Set<URL> processedURLs) { + if (log.isTraceEnabled()) { + log.trace(sm.getString("jarScan.classloaderStart")); + } + + ClassLoader stopLoader = null; + if (!isScanBootstrapClassPath()) { + // Stop when we reach the bootstrap class loader + stopLoader = ClassLoader.getSystemClassLoader().getParent(); + } + + ClassLoader classLoader = context.getClassLoader(); + + // JARs are treated as application provided until the common class + // loader is reached. + boolean isWebapp = true; + + while (classLoader != null && classLoader != stopLoader) { + if (classLoader instanceof URLClassLoader) { + if (isWebapp) { + isWebapp = isWebappClassLoader(classLoader); + } + + // Use a Deque so URLs can be removed as they are processed + // and new URLs can be added as they are discovered during + // processing. + Deque<URL> classPathUrlsToProcess = new LinkedList<>(); + classPathUrlsToProcess.addAll( + Arrays.asList(((URLClassLoader) classLoader).getURLs())); + + if (JreCompat.isJre9Available()) { + // The application and platform class loaders are not + // instances of URLClassLoader. Use the class path in this + // case. + addClassPath(classPathUrlsToProcess); + + // TODO Java 9 module path + } - // JARs are treated as application provided until the common class - // loader is reached. - boolean isWebapp = true; - - while (classLoader != null && classLoader != stopLoader) { - if (classLoader instanceof URLClassLoader) { - if (isWebapp) { - isWebapp = isWebappClassLoader(classLoader); + while (!classPathUrlsToProcess.isEmpty()) { + URL url = classPathUrlsToProcess.pop(); + + if (processedURLs.contains(url)) { + // Skip this URL it has already been processed + continue; } - // Use a Deque so URLs can be removed as they are processed - // and new URLs can be added as they are discovered during - // processing. - Deque<URL> classPathUrlsToProcess = new LinkedList<>(); - classPathUrlsToProcess.addAll( - Arrays.asList(((URLClassLoader) classLoader).getURLs())); - - while (!classPathUrlsToProcess.isEmpty()) { - URL url = classPathUrlsToProcess.pop(); - - if (processedURLs.contains(url)) { - // Skip this URL it has already been processed - continue; - } + ClassPathEntry cpe = new ClassPathEntry(url); - // TODO: Java 9 support. Details are TBD. It will depend - // on the extent to which Java 8 supports the - // Java 9 file formats since this code MUST run on - // Java 8. - ClassPathEntry cpe = new ClassPathEntry(url); - - // JARs are scanned unless the filter says not to. - // Directories are scanned for pluggability scans or - // if scanAllDirectories is enabled unless the - // filter says not to. - if ((cpe.isJar() || - scanType == JarScanType.PLUGGABILITY || - isScanAllDirectories()) && - getJarScanFilter().check(scanType, - cpe.getName())) { - if (log.isDebugEnabled()) { - log.debug(sm.getString("jarScan.classloaderJarScan", url)); - } - try { - processedURLs.add(url); - process(scanType, callback, url, null, isWebapp, classPathUrlsToProcess); - } catch (IOException ioe) { - log.warn(sm.getString("jarScan.classloaderFail", url), ioe); - } - } else { - // JAR / directory has been skipped - if (log.isTraceEnabled()) { - log.trace(sm.getString("jarScan.classloaderJarNoScan", url)); - } + // JARs are scanned unless the filter says not to. + // Directories are scanned for pluggability scans or + // if scanAllDirectories is enabled unless the + // filter says not to. + if ((cpe.isJar() || + scanType == JarScanType.PLUGGABILITY || + isScanAllDirectories()) && + getJarScanFilter().check(scanType, + cpe.getName())) { + if (log.isDebugEnabled()) { + log.debug(sm.getString("jarScan.classloaderJarScan", url)); + } + try { + processedURLs.add(url); + process(scanType, callback, url, null, isWebapp, classPathUrlsToProcess); + } catch (IOException ioe) { + log.warn(sm.getString("jarScan.classloaderFail", url), ioe); + } + } else { + // JAR / directory has been skipped + if (log.isTraceEnabled()) { + log.trace(sm.getString("jarScan.classloaderJarNoScan", url)); } } } - classLoader = classLoader.getParent(); + } + classLoader = classLoader.getParent(); + } + } + + + protected void addClassPath(Deque<URL> classPathUrlsToProcess) { + String classPath = System.getProperty("java.class.path"); + + if (classPath == null || classPath.length() == 0) { + return; + } + + String[] classPathEntries = classPath.split(File.pathSeparator); + for (String classPathEntry : classPathEntries) { + File f = new File(classPath); + try { + classPathUrlsToProcess.add(f.toURI().toURL()); + } catch (MalformedURLException e) { + log.warn(sm.getString("jarScan.classPath.badEntry", classPathEntry), e); } } } @@ -326,7 +354,7 @@ public class StandardJarScanner implemen * Scan a URL for JARs with the optional extensions to look at all files * and all directories. */ - private void process(JarScanType scanType, JarScannerCallback callback, + protected void process(JarScanType scanType, JarScannerCallback callback, URL url, String webappPath, boolean isWebapp, Deque<URL> classPathUrlsToProcess) throws IOException { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org