/* * Copyright 2016-present Facebook, Inc. * * 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.facebook.buck.jvm.java.testutil.compiler; import java.net.URL; import java.net.URLClassLoader; import javax.tools.ToolProvider; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.InitializationError; /** * Test runner that enables tests to work with the Compiler Tree API implementation corresponding to * the compiler returned by {@link ToolProvider#getSystemJavaCompiler()}. These are public APIs that * are not provided in rt.jar and thus are not usually on the classpath. */ public class CompilerTreeApiTestRunner extends BlockJUnit4ClassRunner { private static final TestClassLoader TEST_CLASS_LOADER = new TestClassLoader(); public CompilerTreeApiTestRunner(Class<?> klass) throws InitializationError { // The way runners work, the test class has already been loaded (that's how it knows which // runner to use). We'll ignore that one, though, and load the version from our class loader // which has access to the Compiler Tree API. This is hacky and wrong, but it's test code. :-) super(reloadFromCompilerClassLoader(klass)); } public static Class<?> reloadFromCompilerClassLoader(Class<?> clazz) throws InitializationError { try { return Class.forName(clazz.getName(), true, TEST_CLASS_LOADER); } catch (ClassNotFoundException e) { throw new InitializationError(e); } } private static class TestClassLoader extends URLClassLoader { public TestClassLoader() { super(getSystemClassLoaderUrls(), ToolProvider.getSystemToolClassLoader()); } private static URL[] getSystemClassLoaderUrls() { URLClassLoader systemClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader(); return systemClassLoader.getURLs(); } @Override public Class<?> loadClass(String name) throws ClassNotFoundException { if (shouldLoadClass(name)) { // Under ordinary circumstances doing this is a gross violation of the ClassLoader contract, // because all of these classes can in fact be loaded by one of our parents. If someone // already did load them via one of our parents, we could get weird casting errors. // // However, this is test code, we're loading the test cases themselves with this // ClassLoader, so Everything Will Be Fine(tm). return super.findClass(name); } return super.loadClass(name); } } private static boolean shouldLoadClass(String name) { return name.startsWith("com.facebook.buck"); } }