aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/java_tools
diff options
context:
space:
mode:
authorGravatar Liam Miller-Cushon <cushon@google.com>2015-02-18 18:20:15 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-02-18 18:20:15 +0000
commitca52a6ca2a4c1272eed161405897a57e53ad6b38 (patch)
tree52d52ce789998b4b14f0485b26b81cafd6541ab0 /src/java_tools
parentd46060f124cd970632b07f539fe00489e57a2c60 (diff)
Prepare strict deps for using JavacPathFileManager.
This lays the groundwork for using a JavacPathFileManager and Jimfs to test strict deps and the dependency extractor, instead of the ad-hoc in-memory filesystem implementation in InMemoryJavaFileManager. The current implementation is deeply impressive, but scary to maintain and entirely unnecessary now that we have nio-based filemangers Jimfs. RELNOTES: N/A -- MOS_MIGRATED_REVID=86606317
Diffstat (limited to 'src/java_tools')
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/ImplicitDependencyExtractor.java152
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java69
2 files changed, 140 insertions, 81 deletions
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/ImplicitDependencyExtractor.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/ImplicitDependencyExtractor.java
index df7190d787..6d7d99e580 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/ImplicitDependencyExtractor.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/ImplicitDependencyExtractor.java
@@ -14,24 +14,27 @@
package com.google.devtools.build.buildjar.javac.plugins.dependency;
+import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.view.proto.Deps;
+import com.sun.nio.zipfs.ZipFileSystem;
+import com.sun.nio.zipfs.ZipPath;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.file.ZipArchive;
import com.sun.tools.javac.file.ZipFileIndexArchive;
+import com.sun.tools.javac.nio.JavacPathFileManager;
import com.sun.tools.javac.util.Context;
-import java.io.IOError;
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.HashSet;
+import java.io.File;
+import java.nio.file.Path;
import java.util.Map;
import java.util.Set;
import javax.lang.model.util.SimpleTypeVisitor7;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
/**
@@ -59,7 +62,7 @@ public class ImplicitDependencyExtractor {
JavaFileManager fileManager) {
this.depsSet = depsSet;
this.depsMap = depsMap;
- this.fileManager = fileManager;
+ this.fileManager = unwrapFileManager(fileManager);
}
/**
@@ -85,40 +88,45 @@ public class ImplicitDependencyExtractor {
root.type.accept(typeVisitor, null);
}
- Set<JavaFileObject> platformClasses = getPlatformClasses(fileManager);
+ Set<String> platformJars = getPlatformJars(fileManager);
// Collect all other partially resolved types
for (ClassSymbol cs : symtab.classes.values()) {
if (cs.classfile != null) {
- collectJarOf(cs.classfile, platformClasses);
+ collectJarOf(cs.classfile, platformJars);
} else if (cs.sourcefile != null) {
- collectJarOf(cs.sourcefile, platformClasses);
+ collectJarOf(cs.sourcefile, platformJars);
}
}
}
/**
- * Collect the set of classes on the compilation bootclasspath.
- *
- * <p>TODO(bazel-team): this needs some work. JavaFileManager.list() is slower than
- * StandardJavaFileManager.getLocation() and doesn't get cached. Additionally, tracking all
- * classes in the bootclasspath requires a much bigger set than just tracking a list of jars.
- * However, relying on the context containing a StandardJavaFileManager is brittle (e.g. Lombok
- * wraps the file-manager in a ForwardingJavaFileManager.)
+ * Collect the set of jars on the compilation bootclasspath.
*/
- public static HashSet<JavaFileObject> getPlatformClasses(JavaFileManager fileManager) {
- HashSet<JavaFileObject> result = new HashSet<JavaFileObject>();
- Iterable<JavaFileObject> files;
- try {
- files = fileManager.list(
- StandardLocation.PLATFORM_CLASS_PATH, "", EnumSet.of(JavaFileObject.Kind.CLASS), true);
- } catch (IOException e) {
- throw new IOError(e);
+ public static Set<String> getPlatformJars(JavaFileManager fileManager) {
+
+ if (fileManager instanceof StandardJavaFileManager) {
+ StandardJavaFileManager sjfm = (StandardJavaFileManager) fileManager;
+ ImmutableSet.Builder<String> result = ImmutableSet.builder();
+ for (File jar : sjfm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) {
+ result.add(jar.toString());
+ }
+ return result.build();
}
- for (JavaFileObject file : files) {
- result.add(file);
+
+ if (fileManager instanceof JavacPathFileManager) {
+ JavacPathFileManager jpfm = (JavacPathFileManager) fileManager;
+ ImmutableSet.Builder<String> result = ImmutableSet.builder();
+ for (Path jar : jpfm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) {
+ result.add(jar.toString());
+ }
+ return result.build();
}
- return result;
+
+ // TODO(cushon): Assuming JavacPathFileManager or StandardJavaFileManager is slightly brittle,
+ // but in practice those are the only implementations that matter.
+ throw new IllegalStateException("Unsupported file manager type: "
+ + fileManager.getClass().toString());
}
/**
@@ -126,25 +134,50 @@ public class ImplicitDependencyExtractor {
* to the collection, filtering out jars on the compilation bootclasspath.
*
* @param reference JavaFileObject representing a class or source file
- * @param platformClasses classes on javac's bootclasspath
+ * @param platformJars classes on javac's bootclasspath
*/
- private void collectJarOf(JavaFileObject reference, Set<JavaFileObject> platformClasses) {
- reference = unwrapFileObject(reference);
- if (reference instanceof ZipArchive.ZipFileObject ||
- reference instanceof ZipFileIndexArchive.ZipFileIndexFileObject) {
+ private void collectJarOf(JavaFileObject reference, Set<String> platformJars) {
+
+ String name = getJarName(fileManager, reference);
+ if (name == null) {
+ return;
+ }
+
+ // Filter out classes in rt.jar
+ if (platformJars.contains(name)) {
+ return;
+ }
+
+ depsSet.add(name);
+ if (!depsMap.containsKey(name)) {
+ depsMap.put(name, Deps.Dependency.newBuilder()
+ .setKind(Deps.Dependency.Kind.IMPLICIT)
+ .setPath(name)
+ .build());
+ }
+ }
+
+ public static String getJarName(JavaFileManager fileManager, JavaFileObject file) {
+ file = unwrapFileObject(file);
+
+ if (file instanceof ZipArchive.ZipFileObject
+ || file instanceof ZipFileIndexArchive.ZipFileIndexFileObject) {
// getName() will return something like com/foo/libfoo.jar(Bar.class)
- String name = reference.getName().split("\\(")[0];
- // Filter out classes in rt.jar
- if (!platformClasses.contains(reference)) {
- depsSet.add(name);
- if (!depsMap.containsKey(name)) {
- depsMap.put(name, Deps.Dependency.newBuilder()
- .setKind(Deps.Dependency.Kind.IMPLICIT)
- .setPath(name)
- .build());
- }
+ return file.getName().split("\\(")[0];
+ }
+
+ if (fileManager instanceof JavacPathFileManager) {
+ JavacPathFileManager fm = (JavacPathFileManager) fileManager;
+ Path path = fm.getPath(file);
+ if (!(path instanceof ZipPath)) {
+ return null;
}
+ ZipFileSystem zipfs = ((ZipPath) path).getFileSystem();
+ // calls toString() on the path to the zip archive
+ return zipfs.toString();
}
+
+ return null;
}
@@ -152,19 +185,23 @@ public class ImplicitDependencyExtractor {
// TODO(bazel-team): Override the visitor methods we're interested in.
}
- private static final Class<?> WRAPPED_JAVA_FILE_OBJECT =
- getClassOrDie("com.sun.tools.javac.api.ClientCodeWrapper$WrappedJavaFileObject");
+ private static final Class<?> WRAPPED_FILE_OBJECT =
+ getClassOrDie("com.sun.tools.javac.api.ClientCodeWrapper$WrappedFileObject");
- private static final java.lang.reflect.Field UNWRAP_FIELD =
- getFieldOrDie(
- getClassOrDie("com.sun.tools.javac.api.ClientCodeWrapper$WrappedFileObject"),
- "clientFileObject");
+ private static final java.lang.reflect.Field UNWRAP_FILE_FIELD =
+ getFieldOrDie(WRAPPED_FILE_OBJECT, "clientFileObject");
+
+ private static final Class<?> WRAPPED_JAVA_FILE_MANAGER =
+ getClassOrDie("com.sun.tools.javac.api.ClientCodeWrapper$WrappedJavaFileManager");
+
+ private static final java.lang.reflect.Field UNWRAP_FILE_MANAGER_FIELD =
+ getFieldOrDie(WRAPPED_JAVA_FILE_MANAGER, "clientJavaFileManager");
private static Class<?> getClassOrDie(String name) {
try {
return Class.forName(name);
- } catch (ClassNotFoundException e) {
- throw new LinkageError(e.getMessage());
+ } catch (ReflectiveOperationException e) {
+ throw new LinkageError(e.getMessage(), e);
}
}
@@ -174,16 +211,27 @@ public class ImplicitDependencyExtractor {
field.setAccessible(true);
return field;
} catch (ReflectiveOperationException e) {
- throw new LinkageError(e.getMessage());
+ throw new LinkageError(e.getMessage(), e);
}
}
public static JavaFileObject unwrapFileObject(JavaFileObject file) {
- if (!file.getClass().equals(WRAPPED_JAVA_FILE_OBJECT)) {
+ if (!WRAPPED_FILE_OBJECT.isInstance(file)) {
return file;
}
try {
- return (JavaFileObject) UNWRAP_FIELD.get(file);
+ return (JavaFileObject) UNWRAP_FILE_FIELD.get(file);
+ } catch (ReflectiveOperationException e) {
+ throw new LinkageError(e.getMessage());
+ }
+ }
+
+ public static JavaFileManager unwrapFileManager(JavaFileManager fileManager) {
+ if (!WRAPPED_JAVA_FILE_MANAGER.isInstance(fileManager)) {
+ return fileManager;
+ }
+ try {
+ return (JavaFileManager) UNWRAP_FILE_MANAGER_FIELD.get(fileManager);
} catch (ReflectiveOperationException e) {
throw new LinkageError(e.getMessage());
}
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
index 6ad6d58c7c..35eaf9c2f6 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/buildjar/javac/plugins/dependency/StrictJavaDepsPlugin.java
@@ -15,7 +15,8 @@
package com.google.devtools.build.buildjar.javac.plugins.dependency;
import static com.google.devtools.build.buildjar.javac.plugins.dependency.DependencyModule.StrictJavaDeps.ERROR;
-import static com.google.devtools.build.buildjar.javac.plugins.dependency.ImplicitDependencyExtractor.getPlatformClasses;
+import static com.google.devtools.build.buildjar.javac.plugins.dependency.ImplicitDependencyExtractor.getPlatformJars;
+import static com.google.devtools.build.buildjar.javac.plugins.dependency.ImplicitDependencyExtractor.unwrapFileManager;
import static com.google.devtools.build.buildjar.javac.plugins.dependency.ImplicitDependencyExtractor.unwrapFileObject;
import com.google.common.annotations.VisibleForTesting;
@@ -30,8 +31,6 @@ import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
-import com.sun.tools.javac.file.ZipArchive;
-import com.sun.tools.javac.file.ZipFileIndexArchive;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
@@ -86,6 +85,8 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
private static Properties targetMap;
+ private JavaFileManager fileManager;
+
private PrintWriter errWriter;
/**
@@ -112,15 +113,15 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
public void init(Context context, Log log, JavaCompiler compiler) {
super.init(context, log, compiler);
errWriter = log.getWriter(WriterKind.ERROR);
- JavaFileManager fileManager = context.get(JavaFileManager.class);
+ this.fileManager = unwrapFileManager(context.get(JavaFileManager.class));
implicitDependencyExtractor = new ImplicitDependencyExtractor(
dependencyModule.getUsedClasspath(), dependencyModule.getImplicitDependenciesMap(),
fileManager);
checkingTreeScanner = context.get(CheckingTreeScanner.class);
if (checkingTreeScanner == null) {
- Set<JavaFileObject> platformClasses = getPlatformClasses(fileManager);
+ Set<String> platformJars = getPlatformJars(fileManager);
checkingTreeScanner = new CheckingTreeScanner(
- dependencyModule, log, missingTargets, platformClasses);
+ dependencyModule, log, missingTargets, platformJars, fileManager);
context.put(CheckingTreeScanner.class, checkingTreeScanner);
}
initTargetMap();
@@ -196,6 +197,9 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
/** All error reporting is done through javac's log, */
private final Log log;
+ /** The compilation's file manager. */
+ private final JavaFileManager fileManager;
+
/** The strict_java_deps mode */
private final StrictJavaDeps strictJavaDepsMode;
@@ -209,17 +213,18 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
private final Set<ClassSymbol> seenClasses = new HashSet<>();
private final Set<String> seenTargets = new HashSet<>();
- /** The set of classes on the compilation bootclasspath. */
- private final Set<JavaFileObject> platformClasses;
+ /** The set of jars on the compilation bootclasspath. */
+ private final Set<String> platformJars;
public CheckingTreeScanner(DependencyModule dependencyModule, Log log,
- Set<String> missingTargets, Set<JavaFileObject> platformClasses) {
+ Set<String> missingTargets, Set<String> platformJars, JavaFileManager fileManager) {
this.indirectJarsToTargets = dependencyModule.getIndirectMapping();
this.strictJavaDepsMode = dependencyModule.getStrictJavaDeps();
this.log = log;
this.missingTargets = missingTargets;
this.directDependenciesMap = dependencyModule.getExplicitDependenciesMap();
- this.platformClasses = platformClasses;
+ this.platformJars = platformJars;
+ this.fileManager = fileManager;
}
Set<ClassSymbol> getSeenClasses() {
@@ -236,7 +241,7 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
}
Symbol.TypeSymbol sym = node.type.tsym;
- String jarName = getJarName(sym.enclClass(), platformClasses);
+ String jarName = getJarName(fileManager, sym.enclClass(), platformJars);
// If this type symbol comes from a class file loaded from a jar, check
// whether that jar was a direct dependency and error out otherwise.
@@ -381,26 +386,32 @@ public final class StrictJavaDepsPlugin extends BlazeJavaCompilerPlugin {
* Returns the name of the jar file from which the given class symbol was
* loaded, if available, and null otherwise. Implicitly filters out jars
* from the compilation bootclasspath.
- * @param platformClasses classes on javac's bootclasspath
+ * @param platformJars jars on javac's bootclasspath
*/
- static String getJarName(ClassSymbol classSymbol, Set<JavaFileObject> platformClasses) {
- if (classSymbol != null) {
- // Ignore symbols that appear in the sourcepath:
- if (haveSourceForSymbol(classSymbol)) {
- return null;
- }
- JavaFileObject classfile = unwrapFileObject(classSymbol.classfile);
- if (classfile instanceof ZipArchive.ZipFileObject
- || classfile instanceof ZipFileIndexArchive.ZipFileIndexFileObject) {
- String name = classfile.getName();
- // Here name will be something like blaze-out/.../com/foo/libfoo.jar(Bar.class)
- String jarName = name.split("\\(")[0];
- if (!platformClasses.contains(classfile)) {
- return jarName;
- }
- }
+ static String getJarName(
+ JavaFileManager fileManager, ClassSymbol classSymbol, Set<String> platformJars) {
+ if (classSymbol == null) {
+ return null;
+ }
+
+ // Ignore symbols that appear in the sourcepath:
+ if (haveSourceForSymbol(classSymbol)) {
+ return null;
}
- return null;
+
+ JavaFileObject classfile = unwrapFileObject(classSymbol.classfile);
+
+ String name = ImplicitDependencyExtractor.getJarName(fileManager, classfile);
+ if (name == null) {
+ return null;
+ }
+
+ // Filter out classes in rt.jar
+ if (platformJars.contains(classfile)) {
+ return null;
+ }
+
+ return name;
}
/**