aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java52
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/AbstractJavacTurbineCompilationTest.java140
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD41
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java166
-rw-r--r--src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/ProcessorClasspathTest.java110
5 files changed, 355 insertions, 154 deletions
diff --git a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java
index 4f554a7797..609149a94b 100644
--- a/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java
+++ b/src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac/JavacTurbineCompiler.java
@@ -23,6 +23,7 @@ import com.google.common.jimfs.Jimfs;
import com.google.devtools.build.buildjar.javac.plugins.dependency.StrictJavaDepsPlugin;
import com.google.devtools.build.java.turbine.javac.JavacTurbineCompileResult.Status;
import com.sun.source.util.JavacTask;
+import com.sun.tools.javac.api.ClientCodeWrapper.Trusted;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.CacheFSInfo;
import com.sun.tools.javac.file.JavacFileManager;
@@ -30,6 +31,9 @@ import com.sun.tools.javac.util.Context;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.nio.file.FileSystem;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
@@ -39,6 +43,7 @@ import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Objects;
import javax.annotation.Nullable;
import javax.tools.StandardLocation;
@@ -56,7 +61,7 @@ public class JavacTurbineCompiler {
setupContext(context, request.strictJavaDepsPlugin(), request.transitivePlugin());
CacheFSInfo.preRegister(context);
try (FileSystem fs = Jimfs.newFileSystem(Configuration.forCurrentPlatform());
- JavacFileManager fm = new JavacFileManager(new Context(), false, UTF_8)) {
+ JavacFileManager fm = new ClassloaderMaskingFileManager()) {
JavacTask task =
JavacTool.create()
.getTask(
@@ -105,6 +110,51 @@ public class JavacTurbineCompiler {
return new JavacTurbineCompileResult(ImmutableMap.copyOf(files), status, sw, context);
}
+ /** Mask the annotation processor classpath to avoid version skew. */
+ @Trusted
+ private static class ClassloaderMaskingFileManager extends JavacFileManager {
+
+ public ClassloaderMaskingFileManager() {
+ super(new Context(), false, UTF_8);
+ }
+
+ @Override
+ protected ClassLoader getClassLoader(URL[] urls) {
+ return new URLClassLoader(
+ urls,
+ new ClassLoader(null) {
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ Class<?> c = Class.forName(name);
+ if (name.startsWith("com.sun.source.") || name.startsWith("com.sun.tools.")) {
+ return c;
+ }
+ if (c.getClassLoader() == null
+ || Objects.equals(getClassLoaderName(c.getClassLoader()), "platform")) {
+ return c;
+ }
+ throw new ClassNotFoundException(name);
+ }
+ });
+ }
+ }
+
+ // TODO(cushon): remove this use of reflection if Java 9 is released.
+ private static String getClassLoaderName(ClassLoader classLoader) {
+ Method method;
+ try {
+ method = ClassLoader.class.getMethod("getName");
+ } catch (NoSuchMethodException e) {
+ // ClassLoader#getName doesn't exist in JDK 8 and earlier.
+ return null;
+ }
+ try {
+ return (String) method.invoke(classLoader, new Object[] {});
+ } catch (ReflectiveOperationException e) {
+ throw new LinkageError(e.getMessage(), e);
+ }
+ }
+
static void setupContext(
Context context, @Nullable StrictJavaDepsPlugin sjd, JavacTransitive transitive) {
JavacTurbineJavaCompiler.preRegister(context, sjd, transitive);
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/AbstractJavacTurbineCompilationTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/AbstractJavacTurbineCompilationTest.java
new file mode 100644
index 0000000000..8a7e52f6fd
--- /dev/null
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/AbstractJavacTurbineCompilationTest.java
@@ -0,0 +1,140 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.java.turbine.javac;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.base.Splitter;
+import com.google.common.io.ByteStreams;
+import com.google.devtools.build.java.turbine.javac.JavacTurbine.Result;
+import com.google.turbine.options.TurbineOptions;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.util.Textifier;
+import org.objectweb.asm.util.TraceClassVisitor;
+
+public abstract class AbstractJavacTurbineCompilationTest {
+
+ @Rule public final TemporaryFolder temp = new TemporaryFolder();
+
+ Path sourcedir;
+ List<Path> sources;
+ Path tempdir;
+ Path output;
+ Path outputDeps;
+
+ final TurbineOptions.Builder optionsBuilder = TurbineOptions.builder();
+
+ @Before
+ public void setUp() throws IOException {
+ sourcedir = temp.newFolder().toPath();
+ tempdir = temp.newFolder("_temp").toPath();
+ output = temp.newFile("out.jar").toPath();
+ outputDeps = temp.newFile("out.jdeps").toPath();
+
+ sources = new ArrayList<>();
+
+ optionsBuilder
+ .setOutput(output.toString())
+ .setTempDir(tempdir.toString())
+ .addBootClassPathEntries(
+ Splitter.on(':')
+ .splitToList(System.getProperty("sun.boot.class.path"))
+ .stream()
+ .map(e -> Paths.get(e).toAbsolutePath().toString())
+ .collect(toImmutableList()))
+ .setOutputDeps(outputDeps.toString())
+ .addAllJavacOpts(Arrays.asList("-source", "8", "-target", "8"))
+ .setTargetLabel("//test")
+ .setRuleKind("java_library");
+ }
+
+ protected void addSourceLines(String path, String... lines) throws IOException {
+ Path source = sourcedir.resolve(path);
+ sources.add(source);
+ Files.write(source, Arrays.asList(lines), UTF_8);
+ }
+
+ protected void compile() throws IOException {
+ optionsBuilder.addSources(sources.stream().map(p -> p.toString()).collect(toImmutableList()));
+ try (JavacTurbine turbine =
+ new JavacTurbine(
+ new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8))),
+ optionsBuilder.build())) {
+ assertThat(turbine.compile()).isEqualTo(Result.OK_WITH_REDUCED_CLASSPATH);
+ }
+ }
+
+ protected Map<String, byte[]> collectOutputs() throws IOException {
+ return collectFiles(output);
+ }
+
+ static Map<String, byte[]> collectFiles(Path jar) throws IOException {
+ Map<String, byte[]> files = new LinkedHashMap<>();
+ try (JarFile jf = new JarFile(jar.toFile())) {
+ Enumeration<JarEntry> entries = jf.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry entry = entries.nextElement();
+ files.put(entry.getName(), ByteStreams.toByteArray(jf.getInputStream(entry)));
+ }
+ }
+ return files;
+ }
+
+ static String textify(byte[] bytes) {
+ StringWriter sw = new StringWriter();
+ ClassReader cr = new ClassReader(bytes);
+ cr.accept(new TraceClassVisitor(null, new Textifier(), new PrintWriter(sw, true)), 0);
+ return sw.toString();
+ }
+
+ protected Path createClassJar(String jarName, Class<?>... classes) throws IOException {
+ Path jarPath = temp.newFile(jarName).toPath();
+ try (OutputStream os = Files.newOutputStream(jarPath);
+ JarOutputStream jos = new JarOutputStream(os)) {
+ for (Class<?> clazz : classes) {
+ String classFileName = clazz.getName().replace('.', '/') + ".class";
+ jos.putNextEntry(new JarEntry(classFileName));
+ try (InputStream is = getClass().getClassLoader().getResourceAsStream(classFileName)) {
+ ByteStreams.copy(is, jos);
+ }
+ }
+ }
+ return jarPath;
+ }
+}
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD
index 344b4d6e97..50082fe6fb 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/BUILD
@@ -1,5 +1,22 @@
package(default_visibility = ["//src:__subpackages__"])
+java_library(
+ name = "AbstractJavacTurbineCompilationTest",
+ testonly = 1,
+ srcs = ["AbstractJavacTurbineCompilationTest.java"],
+ deps = [
+ "//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac:javac_turbine",
+ "//src/main/protobuf:deps_java_proto",
+ "//third_party:asm",
+ "//third_party:asm-util",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ "//third_party:turbine",
+ "//third_party/java/jdk/langtools:javac",
+ ],
+)
+
java_test(
name = "JavacTurbineTest",
srcs = ["JavacTurbineTest.java"],
@@ -11,7 +28,31 @@ java_test(
"-Xbootclasspath/p:$(location //third_party/java/jdk/langtools:javac_jar)",
],
deps = [
+ ":AbstractJavacTurbineCompilationTest",
+ "//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac:javac_turbine",
+ "//src/main/protobuf:deps_java_proto",
+ "//third_party:asm",
+ "//third_party:asm-util",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ "//third_party:turbine",
+ "//third_party/java/jdk/langtools:javac",
+ ],
+)
+
+java_test(
+ name = "ProcessorClasspathTest_bootclasspath",
+ srcs = ["//src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac:ProcessorClasspathTest.java"],
+ data = ["//third_party/java/jdk/langtools:javac_jar"],
+ jvm_flags = [
+ # Simulates how Bazel invokes turbine
+ "-Xbootclasspath/p:$(location //third_party/java/jdk/langtools:javac_jar)",
+ ],
+ test_class = "com.google.devtools.build.java.turbine.javac.ProcessorClasspathTest",
+ deps = [
"//src/java_tools/buildjar/java/com/google/devtools/build/java/turbine/javac:javac_turbine",
+ "//src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac:AbstractJavacTurbineCompilationTest",
"//src/main/protobuf:deps_java_proto",
"//third_party:asm",
"//third_party:asm-util",
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
index ac386f7d62..6c24a732d4 100644
--- a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/JavacTurbineTest.java
@@ -14,7 +14,6 @@
package com.google.devtools.build.java.turbine.javac;
-import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -28,7 +27,6 @@ import com.google.common.io.ByteStreams;
import com.google.devtools.build.java.turbine.javac.JavacTurbine.Result;
import com.google.devtools.build.lib.view.proto.Deps;
import com.google.devtools.build.lib.view.proto.Deps.Dependency;
-import com.google.turbine.options.TurbineOptions;
import com.sun.source.tree.LiteralTree;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TaskEvent;
@@ -43,7 +41,6 @@ import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.IOError;
import java.io.IOException;
-import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
@@ -52,10 +49,8 @@ import java.net.URI;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -80,10 +75,7 @@ import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardLocation;
-import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.objectweb.asm.ClassReader;
@@ -92,61 +84,7 @@ import org.objectweb.asm.util.TraceClassVisitor;
/** Unit tests for {@link JavacTurbine}. */
@RunWith(JUnit4.class)
-public class JavacTurbineTest {
-
- @Rule public final TemporaryFolder temp = new TemporaryFolder();
-
- Path sourcedir;
- List<Path> sources;
- Path tempdir;
- Path output;
- Path outputDeps;
-
- final TurbineOptions.Builder optionsBuilder = TurbineOptions.builder();
-
- @Before
- public void setUp() throws IOException {
- sourcedir = temp.newFolder().toPath();
- tempdir = temp.newFolder("_temp").toPath();
- output = temp.newFile("out.jar").toPath();
- outputDeps = temp.newFile("out.jdeps").toPath();
-
- sources = new ArrayList<>();
-
- optionsBuilder
- .setOutput(output.toString())
- .setTempDir(tempdir.toString())
- .addBootClassPathEntries(
- Splitter.on(':')
- .splitToList(System.getProperty("sun.boot.class.path"))
- .stream()
- .map(e -> Paths.get(e).toAbsolutePath().toString())
- .collect(toImmutableList()))
- .setOutputDeps(outputDeps.toString())
- .addAllJavacOpts(Arrays.asList("-source", "8", "-target", "8"))
- .setTargetLabel("//test")
- .setRuleKind("java_library");
- }
-
- private void addSourceLines(String path, String... lines) throws IOException {
- Path source = sourcedir.resolve(path);
- sources.add(source);
- Files.write(source, Arrays.asList(lines), UTF_8);
- }
-
- void compile() throws IOException {
- optionsBuilder.addSources(ImmutableList.copyOf(Iterables.transform(sources, TO_STRING)));
- try (JavacTurbine turbine =
- new JavacTurbine(
- new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.err, UTF_8))),
- optionsBuilder.build())) {
- assertThat(turbine.compile()).isEqualTo(Result.OK_WITH_REDUCED_CLASSPATH);
- }
- }
-
- private Map<String, byte[]> collectOutputs() throws IOException {
- return collectFiles(output);
- }
+public class JavacTurbineTest extends AbstractJavacTurbineCompilationTest {
@Test
public void hello() throws Exception {
@@ -904,86 +842,6 @@ public class JavacTurbineTest {
assertThat(text).isEqualTo(Joiner.on('\n').join(expected));
}
- @SupportedAnnotationTypes("*")
- public static class HostClasspathProcessor extends AbstractProcessor {
-
- @Override
- public SourceVersion getSupportedSourceVersion() {
- return SourceVersion.latest();
- }
-
- boolean first = true;
-
- @Override
- public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- if (!first) {
- return false;
- }
- first = false;
-
- String message;
- try {
- JavacTurbine.class.toString();
- message = "ok";
- } catch (Throwable e) {
- StringWriter stringWriter = new StringWriter();
- e.printStackTrace(new PrintWriter(stringWriter));
- message = stringWriter.toString();
- }
- try {
- FileObject fileObject =
- processingEnv
- .getFiler()
- .createResource(StandardLocation.CLASS_OUTPUT, "", "result.txt");
- try (OutputStream os = fileObject.openOutputStream()) {
- os.write(message.getBytes(UTF_8));
- }
- } catch (IOException e) {
- throw new IOError(e);
- }
- return false;
- }
- }
-
- @Test
- public void maskProcessorClasspath() throws Exception {
- addSourceLines("MyAnnotation.java", "public @interface MyAnnotation {}");
- addSourceLines("Hello.java", "@MyAnnotation class Hello {}");
-
- // create a jar containing only HostClasspathProcessor
- Path processorJar = createClassJar("libprocessor.jar", HostClasspathProcessor.class);
-
- optionsBuilder.addProcessors(ImmutableList.of(HostClasspathProcessor.class.getName()));
- optionsBuilder.addProcessorPathEntries(ImmutableList.of(processorJar.toString()));
- optionsBuilder.addClassPathEntries(ImmutableList.<String>of());
-
- compile();
-
- Map<String, byte[]> outputs = collectOutputs();
- assertThat(outputs.keySet()).contains("result.txt");
-
- String text = new String(outputs.get("result.txt"), UTF_8);
- assertThat(text)
- .contains(
- "java.lang.NoClassDefFoundError:"
- + " com/google/devtools/build/java/turbine/javac/JavacTurbine");
- }
-
- private Path createClassJar(String jarName, Class<?>... classes) throws IOException {
- Path jarPath = temp.newFile(jarName).toPath();
- try (OutputStream os = Files.newOutputStream(jarPath);
- JarOutputStream jos = new JarOutputStream(os)) {
- for (Class<?> clazz : classes) {
- String classFileName = clazz.getName().replace('.', '/') + ".class";
- jos.putNextEntry(new JarEntry(classFileName));
- try (InputStream is = getClass().getClassLoader().getResourceAsStream(classFileName)) {
- ByteStreams.copy(is, jos);
- }
- }
- }
- return jarPath;
- }
-
@Test
public void overlappingSourceJars() throws Exception {
Path sourceJar1 = temp.newFile("srcs1.jar").toPath();
@@ -1187,7 +1045,12 @@ public class JavacTurbineTest {
public void noNativeHeaderOutput() throws Exception {
// deliberately exclude TransitiveDep
- Path deps = createClassJar("libdeps.jar", JavacTurbineTest.class, DirectDep.class);
+ Path deps =
+ createClassJar(
+ "libdeps.jar",
+ AbstractJavacTurbineCompilationTest.class,
+ JavacTurbineTest.class,
+ DirectDep.class);
// compilation will complete supertypes of DirectDep iff NATIVE_HEADER_OUTPUT is set
addSourceLines(
@@ -1211,7 +1074,12 @@ public class JavacTurbineTest {
@Test
public void ignoreStrictDepsErrors() throws Exception {
- Path lib = createClassJar("deps.jar", JavacTurbineTest.class, Lib.class);
+ Path lib =
+ createClassJar(
+ "deps.jar",
+ AbstractJavacTurbineCompilationTest.class,
+ JavacTurbineTest.class,
+ Lib.class);
addSourceLines(
"Hello.java", "import " + Lib.class.getCanonicalName() + ";", "class Hello extends Lib {}");
@@ -1427,11 +1295,3 @@ public class JavacTurbineTest {
}
}
-
-
-
-
-
-
-
-
diff --git a/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/ProcessorClasspathTest.java b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/ProcessorClasspathTest.java
new file mode 100644
index 0000000000..5ee6db1cf5
--- /dev/null
+++ b/src/java_tools/buildjar/javatests/com/google/devtools/build/java/turbine/javac/ProcessorClasspathTest.java
@@ -0,0 +1,110 @@
+// Copyright 2017 The Bazel Authors. All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.java.turbine.javac;
+
+import static com.google.common.collect.ImmutableList.toImmutableList;
+import static com.google.common.truth.Truth.assertThat;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import com.google.common.collect.ImmutableList;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Path;
+import java.util.Map;
+import java.util.Set;
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Unit tests for isolated processor classloading. */
+@RunWith(JUnit4.class)
+public class ProcessorClasspathTest extends AbstractJavacTurbineCompilationTest {
+
+ @SupportedAnnotationTypes("*")
+ public static class HostClasspathProcessor extends AbstractProcessor {
+
+ @Override
+ public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+
+ boolean first = true;
+
+ @Override
+ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (!first) {
+ return false;
+ }
+ first = false;
+
+ String message;
+ try {
+ JavacTurbine.class.toString();
+ message = "ok";
+ } catch (Throwable e) {
+ StringWriter stringWriter = new StringWriter();
+ e.printStackTrace(new PrintWriter(stringWriter));
+ message = stringWriter.toString();
+ }
+ try {
+ FileObject fileObject =
+ processingEnv
+ .getFiler()
+ .createResource(StandardLocation.CLASS_OUTPUT, "", "result.txt");
+ try (OutputStream os = fileObject.openOutputStream()) {
+ os.write(message.getBytes(UTF_8));
+ }
+ } catch (IOException e) {
+ throw new IOError(e);
+ }
+ return false;
+ }
+ }
+
+ @Test
+ public void maskProcessorClasspath() throws Exception {
+ addSourceLines("MyAnnotation.java", "public @interface MyAnnotation {}");
+ addSourceLines("Hello.java", "@MyAnnotation class Hello {}");
+
+ // create a jar containing only HostClasspathProcessor
+ Path processorJar = createClassJar("libprocessor.jar", HostClasspathProcessor.class);
+
+ optionsBuilder.addProcessors(ImmutableList.of(HostClasspathProcessor.class.getName()));
+ optionsBuilder.addProcessorPathEntries(ImmutableList.of(processorJar.toString()));
+ optionsBuilder.addClassPathEntries(ImmutableList.<String>of());
+ optionsBuilder.addSources(sources.stream().map(Object::toString).collect(toImmutableList()));
+
+ compile();
+
+ Map<String, byte[]> outputs = collectOutputs();
+ assertThat(outputs).containsKey("result.txt");
+
+ String text = new String(outputs.get("result.txt"), UTF_8);
+ assertThat(text)
+ .contains(
+ "java.lang.NoClassDefFoundError:"
+ + " com/google/devtools/build/java/turbine/javac/JavacTurbine");
+ }
+}