diff options
author | cushon <cushon@google.com> | 2017-10-05 20:20:46 +0200 |
---|---|---|
committer | Klaus Aehlig <aehlig@google.com> | 2017-10-06 19:47:51 +0200 |
commit | e9cc5120754841baafe2f37d76fcfa8bb63e7d45 (patch) | |
tree | e97fafddfaaf55aed296e6ca50278918850ce9e3 /src/main/java/com/google/devtools/build/lib/util | |
parent | 06d24101e4a77a14e006e37382e5bb25cd56e944 (diff) |
Prepare Classpath reading for Java 9
PiperOrigin-RevId: 171180273
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/util')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/util/Classpath.java | 151 |
1 files changed, 12 insertions, 139 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/util/Classpath.java b/src/main/java/com/google/devtools/build/lib/util/Classpath.java index 7fb48c0140..c976a20b45 100644 --- a/src/main/java/com/google/devtools/build/lib/util/Classpath.java +++ b/src/main/java/com/google/devtools/build/lib/util/Classpath.java @@ -13,29 +13,17 @@ // limitations under the License. package com.google.devtools.build.lib.util; -import java.io.File; +import com.google.common.reflect.ClassPath; +import com.google.common.reflect.ClassPath.ClassInfo; import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -import java.nio.file.Paths; -import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Set; -import java.util.TreeSet; -import java.util.jar.Attributes; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; /** * A helper class to find all classes on the current classpath. This is used to automatically create * JUnit 3 and 4 test suites. */ public final class Classpath { - private static final String CLASS_EXTENSION = ".class"; /** * Base exception for any classpath related errors. @@ -49,135 +37,20 @@ public final class Classpath { /** Finds all classes that live in or below the given package. */ public static Set<Class<?>> findClasses(String packageName) throws ClassPathException { Set<Class<?>> result = new LinkedHashSet<>(); - String pathPrefix = (packageName + '.').replace('.', '/'); - for (String entryName : getClassPath()) { - File classPathEntry = new File(entryName); - if (classPathEntry.exists()) { - try { - Set<String> classNames; - if (classPathEntry.isDirectory()) { - classNames = findClassesInDirectory(classPathEntry, pathPrefix); - } else { - classNames = findClassesInJar(classPathEntry, pathPrefix); - } - for (String className : classNames) { - try { - Class<?> clazz = Class.forName(className); - result.add(clazz); - } catch (UnsatisfiedLinkError | NoClassDefFoundError unused) { - // Ignore: we're most likely running on a different platform. - } - } - } catch (IOException e) { - throw new ClassPathException( - "Can't read classpath entry %s: %s", entryName, e.getMessage()); - } catch (ClassNotFoundException e) { - throw new ClassPathException( - "Class not found even though it is on the classpath %s: %s", - entryName, e.getMessage()); - } - } - } - return result; - } - - private static Set<String> findClassesInDirectory(File classPathEntry, String pathPrefix) { - Set<String> result = new TreeSet<>(); - File directory = new File(classPathEntry, pathPrefix); - innerFindClassesInDirectory(result, directory, pathPrefix); - return result; - } - - /** - * Finds all classes and sub packages in the given directory that are below the given package and - * add them to the respective sets. - * - * @param directory Directory to inspect - * @param pathPrefix Prefix for the path to the classes that are requested - * (ex: {@code com/google/foo/bar}) - */ - private static void innerFindClassesInDirectory(Set<String> classNames, File directory, - String pathPrefix) { - Preconditions.checkArgument(pathPrefix.endsWith("/")); - if (directory.exists()) { - for (File f : directory.listFiles()) { - String name = f.getName(); - if (name.endsWith(CLASS_EXTENSION)) { - String clzName = getClassName(pathPrefix + name); - classNames.add(clzName); - } else if (f.isDirectory()) { - findClassesInDirectory(f, pathPrefix + name + "/"); - } - } - } - } - - /** - * Returns a set of all classes in the jar that start with the given prefix. - */ - private static Set<String> findClassesInJar(File jarFile, String pathPrefix) throws IOException { - Set<String> classNames = new TreeSet<>(); - try (ZipFile zipFile = new ZipFile(jarFile)) { - Enumeration<? extends ZipEntry> entries = zipFile.entries(); - while (entries.hasMoreElements()) { - String entryName = entries.nextElement().getName(); - if (entryName.startsWith(pathPrefix) && entryName.endsWith(CLASS_EXTENSION)) { - classNames.add(getClassName(entryName)); - } - } - } - return classNames; - } - - /** - * Given the absolute path of a class file, return the class name. - */ - private static String getClassName(String className) { - int classNameEnd = className.length() - CLASS_EXTENSION.length(); - return className.substring(0, classNameEnd).replace('/', '.'); - } - - private static void getClassPathsFromClasspathJar(File classpathJar, Set<String> classPaths) - throws IOException, ClassPathException { - Manifest manifest = new JarFile(classpathJar).getManifest(); - Attributes attributes = manifest.getMainAttributes(); - for (String classPath : attributes.getValue("Class-Path").split(" ")) { - try { - classPaths.add(Paths.get(new URI(classPath)).toAbsolutePath().toString()); - } catch (URISyntaxException e) { - throw new ClassPathException( - "Error parsing classpath uri %s: %s", classPath, e.getMessage()); - } - } - } - - /** Gets the classpath from current classloader. */ - private static Set<String> getClassPath() throws ClassPathException { - ClassLoader classloader = Classpath.class.getClassLoader(); - if (!(classloader instanceof URLClassLoader)) { - throw new IllegalStateException("Unable to find classes to test, since Test Suite class is " - + "loaded by an unsupported Classloader."); - } - - Set<String> completeClassPaths = new TreeSet<>(); - URL[] urls = ((URLClassLoader) classloader).getURLs(); - for (URL url : urls) { - String entryName = url.getPath(); - completeClassPaths.add(entryName); - if (entryName.endsWith("-classpath.jar")) { - // Bazel creates a classpath jar when the class path length exceeds command line length - // limit, read the class path value from its manifest file if it's a classpath jar. - File classPathEntry = new File(entryName); - if (classPathEntry.exists() && classPathEntry.isFile()) { + String packagePrefix = (packageName + '.').replace('/', '.'); + try { + for (ClassInfo ci : ClassPath.from(Classpath.class.getClassLoader()).getAllClasses()) { + if (ci.getName().startsWith(packagePrefix)) { try { - getClassPathsFromClasspathJar(classPathEntry, completeClassPaths); - } catch (IOException e) { - throw new ClassPathException( - "Can't read classpath entry %s: %s", entryName, e.getMessage()); + result.add(ci.load()); + } catch (UnsatisfiedLinkError | NoClassDefFoundError unused) { + // Ignore: we're most likely running on a different platform. } } } + } catch (IOException e) { + throw new ClassPathException(e.getMessage()); } - return completeClassPaths; + return result; } } |