/** * Copyright 2005-2016 Red Hat, Inc. * * Red Hat licenses this file to you 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 io.fabric8.kubernetes.generator.processor; import javax.annotation.processing.Filer; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.TypeElement; import javax.tools.Diagnostic; import javax.tools.DiagnosticCollector; import javax.tools.DiagnosticListener; import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardLocation; import javax.tools.ToolProvider; import java.io.File; import java.io.IOException; import java.io.Writer; import java.lang.reflect.Field; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class CompilationTaskFactory { private static final String FILE_URL_PREFIX = "file:"; private static final String DISABLE_ANNOTATION_PROCESSORS_OPT = "-proc:none"; private static final String CLASSPATH_OPT = "-classpath"; private static final String FILE_MANAGER_FIELD_NAME = "fileManager"; private final DiagnosticListener<JavaFileObject> diagnosticListener = new DiagnosticCollector<>(); private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); private final ProcessingEnvironment processingEnvironment; private final JavaFileManager fileManager; public CompilationTaskFactory(ProcessingEnvironment processingEnvironment) { this.processingEnvironment = processingEnvironment; this.fileManager = createFileManager(processingEnvironment); } /** * Obtains the {@link javax.tools.JavaFileManager} from the {@link javax.annotation.processing.ProcessingEnvironment}/ * @param processingEnvironment The processing environment. * @return The file manager. */ static JavaFileManager createFileManager(ProcessingEnvironment processingEnvironment) { Filer filer = processingEnvironment.getFiler(); try { Field field = filer.getClass().getDeclaredField(FILE_MANAGER_FIELD_NAME); field.setAccessible(true); return (JavaFileManager) field.get(filer); } catch (Throwable t) { throw new RuntimeException(t); } } /** * Creates a compilation task for the specified {@link javax.lang.model.element.Element} instances. * @param elements The elements. * @return The compilation task. * @throws java.io.IOException */ public JavaCompiler.CompilationTask create(Iterable<TypeElement> elements, Writer writer) throws IOException { Set<String> options = new LinkedHashSet<>(); Set<JavaFileObject> javaFileObjects = new LinkedHashSet<>(); ClassLoader classLoader = getClass().getClassLoader(); if (classLoader instanceof URLClassLoader) { String classPath = createClassPath(((URLClassLoader) classLoader).getURLs()); options.add(DISABLE_ANNOTATION_PROCESSORS_OPT); options.add(CLASSPATH_OPT); options.add(classPath); } for (TypeElement element : elements) { JavaFileObject source = fileManager.getJavaFileForInput(StandardLocation.SOURCE_PATH, element.getQualifiedName().toString(), JavaFileObject.Kind.SOURCE); if (source == null) { throw new IOException("Unable to find class: " + element.getQualifiedName().toString()); } javaFileObjects.add(source); } return compiler.getTask(writer, fileManager, diagnosticListener, options, new ArrayList<String>(), javaFileObjects); } private static String createClassPath(URL[] urls) { StringBuilder sb = new StringBuilder(); boolean first = true; for (URL url : urls) { if (first) { first=false; } else { sb.append(File.pathSeparator); } sb.append(url.toExternalForm().replaceFirst(FILE_URL_PREFIX, "")); } return sb.toString(); } public List<Diagnostic> getCompileDiagnostics() { return ((DiagnosticCollector)diagnosticListener).getDiagnostics(); } }