1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 * 25 */ 26 package jdk.internal.jextract.impl; 27 28 import javax.tools.FileObject; 29 import javax.tools.ForwardingJavaFileManager; 30 import javax.tools.JavaCompiler; 31 import javax.tools.JavaFileManager; 32 import javax.tools.JavaFileObject; 33 import javax.tools.SimpleJavaFileObject; 34 import javax.tools.ToolProvider; 35 import java.io.*; 36 import java.io.Writer; 37 import java.net.URI; 38 import java.util.ArrayList; 39 import java.util.Arrays; 40 import java.util.List; 41 42 final class InMemoryJavaCompiler { 43 private InMemoryJavaCompiler() {} 44 45 static List<JavaFileObject> compile(List<JavaFileObject> files, 46 String... options) { 47 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 48 FileManager fileManager = new FileManager(compiler.getStandardFileManager(null, null, null)); 49 50 Writer writer = new StringWriter(); 51 Boolean exitCode = compiler.getTask(writer, fileManager, null, Arrays.asList(options), null, files).call(); 52 if (!exitCode) { 53 throw new CompilationFailedException("In memory compilation failed: " + writer.toString()); 54 } 55 return fileManager.getCompiledFiles(); 56 } 57 58 static JavaFileObject jfoFromByteArray(URI uri, byte[] bytes) { 59 return new SimpleJavaFileObject(uri, JavaFileObject.Kind.CLASS) { 60 @Override 61 public InputStream openInputStream() { 62 return new ByteArrayInputStream(bytes); 63 } 64 }; 65 } 66 67 static JavaFileObject jfoFromString(URI uri, String contents) { 68 return new SimpleJavaFileObject(uri, JavaFileObject.Kind.SOURCE) { 69 @Override 70 public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { 71 return contents; 72 } 73 }; 74 } 75 76 // Wraper for class byte array 77 private static class ClassFile extends SimpleJavaFileObject { 78 private final ByteArrayOutputStream baos = new ByteArrayOutputStream(); 79 80 protected ClassFile(String name) { 81 super(URI.create(name.replace('.', '/') + Kind.CLASS.extension), Kind.CLASS); 82 } 83 84 @Override 85 public ByteArrayOutputStream openOutputStream() { 86 return this.baos; 87 } 88 89 @Override 90 public InputStream openInputStream() { 91 return new ByteArrayInputStream(baos.toByteArray()); 92 } 93 } 94 95 // File manager which spawns ClassFile instances on demand 96 private static class FileManager extends ForwardingJavaFileManager<JavaFileManager> { 97 private final List<JavaFileObject> compiled = new ArrayList<>(); 98 99 protected FileManager(JavaFileManager fileManager) { 100 super(fileManager); 101 } 102 103 @Override 104 public JavaFileObject getJavaFileForOutput(Location location, String name, JavaFileObject.Kind kind, FileObject source) throws IOException { 105 JavaFileObject out = new ClassFile(name); 106 compiled.add(out); 107 return out; 108 } 109 110 public List<JavaFileObject> getCompiledFiles() { 111 return compiled; 112 } 113 } 114 }