AsgcCOmpiler重构

This commit is contained in:
aoshiguchen
2022-08-25 23:30:06 +08:00
parent c8dff52e9c
commit e60a42c2b2
8 changed files with 508 additions and 123 deletions
@@ -22,16 +22,14 @@
package fun.asgc.neutrino.core.aop.compiler;
import com.google.common.collect.Lists;
import com.sun.tools.javac.resources.compiler;
import fun.asgc.neutrino.core.base.GlobalConfig;
import fun.asgc.neutrino.core.util.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import javax.tools.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -42,23 +40,34 @@ import java.util.stream.Collectors;
@Slf4j
@SuppressWarnings("all")
public class AsgcCompiler {
private static final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
private DiagnosticCollector<JavaFileObject> collector;
private List<String> classpathList;
private final JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();
private final DiagnosticCollector<JavaFileObject> collector;
private final StandardJavaFileManager standardJavaFileManager;
private final List<String> options = new ArrayList<>();
private final List<String> classpathList = new ArrayList<>();
private final Collection<JavaFileObject> compilationUnits = new ArrayList<JavaFileObject>();
private boolean isSaveSourceCodeFile;
private boolean isSaveClassFile;
private String generatorCodeSavePath;
private ByteCodeClassLoader classLoader;
private DynamicClassLoader dynamicClassLoader;
public AsgcCompiler() {
if (null == compiler) {
throw new RuntimeException("Can not get javax.tools.JavaCompiler, check whether \"tools.jar\" is in the environment variable CLASSPATH \nVisit https://jfinal.com/doc/4-8 for details \n");
this(ClassLoader.getSystemClassLoader());
}
public AsgcCompiler(ClassLoader classLoader) {
if (null == javaCompiler) {
throw new RuntimeException("Can not load JavaCompiler from javax.tools.ToolProvider#getSystemJavaCompiler(),\n please confirm the application running in JDK not JRE.");
}
this.collector = new DiagnosticCollector<>();
this.classpathList = Lists.newArrayList();
this.standardJavaFileManager = javaCompiler.getStandardFileManager(collector, null, null);
this.isSaveClassFile = false;
this.generatorCodeSavePath = GlobalConfig.getGeneratorCodeSavePath();
this.classLoader = new ByteCodeClassLoader();
this.dynamicClassLoader = new DynamicClassLoader(classLoader);
addOption("-Xlint:unchecked");
addOption("-source", "1.8");
addOption("-target", "1.8");
}
public void addClasspath(String classpath) {
@@ -78,16 +87,29 @@ public class AsgcCompiler {
}
private List<String> getOptions() {
List<String> options = Lists.newArrayList();
options.add("-source");
options.add("1.8");
options.add("-target");
options.add("1.8");
List<String> list = Lists.newArrayList(options);
if (!CollectionUtil.isEmpty(classpathList)) {
options.add("-classpath");
options.add(classpathList.stream().collect(Collectors.joining(File.pathSeparator)));
list.add("-classpath");
list.add(classpathList.stream().collect(Collectors.joining(File.pathSeparator)));
}
return options;
return list;
}
private void addOption(String option) {
this.options.add(option);
}
private void addOption(String key, String val) {
this.options.add(key);
this.options.add(val);
}
private void addSource(String className, String source) {
addSource(new StringSource(className, source));
}
private void addSource(JavaFileObject javaFileObject) {
compilationUnits.add(javaFileObject);
}
/**
@@ -95,32 +117,17 @@ public class AsgcCompiler {
* @param className 类名
* @param sourceCode 源代码
*/
public Map<String,byte[]> compile(String className, String sourceCode) {
DynamicJavaFileManager javaFileManager = new DynamicJavaFileManager(compiler.getStandardFileManager(collector, null, null));
CharSequenceJavaFileObject javaFileObject = new CharSequenceJavaFileObject(className, sourceCode);
Boolean result = compiler.getTask(null, javaFileManager, collector, getOptions(), null, Arrays.asList(javaFileObject)).call();
public Class<?> compile(String className, String sourceCode) throws ClassNotFoundException {
JavaFileManager javaFileManager = new DynamicJavaFileManager(standardJavaFileManager, dynamicClassLoader);
Boolean result = javaCompiler.getTask(null, javaFileManager, collector, getOptions(), null, Lists.newArrayList(new StringSource(className, sourceCode))).call();
if (!result) {
collector.getDiagnostics().forEach(item -> log.error(item.toString()));
}
Map<String, byte[]> ret = new HashMap<>();
for (Map.Entry<String, CharSequenceJavaFileObject> e : javaFileManager.fileObjects.entrySet()) {
ret.put(e.getKey(), e.getValue().getByteCode());
Map<String, Class<?>> map = dynamicClassLoader.getClasses();
if (CollectionUtil.isEmpty(map)) {
return null;
}
return ret;
}
/**
* 编译并加载类
* @param pkg
* @param className
* @param sourceCode
* @param <T>
* @return
*/
public <T> Class<T> compileAndLoadClass(String pkg, String className, String sourceCode) throws ClassNotFoundException {
Map<String,byte[]> byteCodeMap = compile(className, sourceCode);
classLoader.addByteCode(byteCodeMap);
return (Class<T>)classLoader.loadClass(pkg + "." + className);
return map.values().stream().filter(c -> c.getSimpleName().equals(className)).findFirst().orElseGet(null);
}
}
@@ -0,0 +1,122 @@
/**
* Copyright (c) 2022 aoshiguchen
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package fun.asgc.neutrino.core.aop.compiler;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.NestingKind;
import javax.tools.JavaFileObject;
import java.io.*;
import java.net.URI;
/**
*
* @author: wen.y
* @date: 2022/8/25
*/
public class CustomJavaFileObject implements JavaFileObject {
private final String binaryName;
private final URI uri;
private final String name;
public CustomJavaFileObject(String binaryName, URI uri) {
this.uri = uri;
this.binaryName = binaryName;
name = uri.getPath() == null ? uri.getSchemeSpecificPart() : uri.getPath(); // for FS based URI the path is not null, for JAR URI the scheme specific part is not null
}
@Override
public URI toUri() {
return uri;
}
@Override
public InputStream openInputStream() throws IOException {
return uri.toURL().openStream();
}
@Override
public OutputStream openOutputStream() {
throw new UnsupportedOperationException();
}
@Override
public String getName() {
return name;
}
@Override
public Reader openReader(boolean ignoreEncodingErrors) {
throw new UnsupportedOperationException();
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
throw new UnsupportedOperationException();
}
@Override
public Writer openWriter() throws IOException {
throw new UnsupportedOperationException();
}
@Override
public long getLastModified() {
return 0;
}
@Override
public boolean delete() {
throw new UnsupportedOperationException();
}
@Override
public Kind getKind() {
return Kind.CLASS;
}
@Override
public boolean isNameCompatible(String simpleName, Kind kind) {
String baseName = simpleName + kind.extension;
return kind.equals(getKind())
&& (baseName.equals(getName())
|| getName().endsWith("/" + baseName));
}
@Override
public NestingKind getNestingKind() {
throw new UnsupportedOperationException();
}
@Override
public Modifier getAccessLevel() {
throw new UnsupportedOperationException();
}
public String binaryName() {
return binaryName;
}
@Override
public String toString() {
return this.getClass().getName() + "[" + this.toUri() + "]";
}
}
@@ -21,47 +21,48 @@
*/
package fun.asgc.neutrino.core.aop.compiler;
import fun.asgc.neutrino.core.util.CollectionUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* @author: aoshiguchen
* @date: 2022/8/17
* @author: wen.y
* @date: 2022/8/25
*/
public class ByteCodeClassLoader extends ClassLoader {
private Map<String, byte[]> byteCodeMap = new ConcurrentHashMap<>();
static {
registerAsParallelCapable();
public class DynamicClassLoader extends ClassLoader {
private final Map<String, MemoryByteCode> byteCodes = new HashMap<>();
public DynamicClassLoader(ClassLoader classLoader) {
super(classLoader);
}
public ByteCodeClassLoader() {
super(getParentClassLoader());
}
protected static ClassLoader getParentClassLoader() {
ClassLoader ret = Thread.currentThread().getContextClassLoader();
return ret != null ? ret : ByteCodeClassLoader.class.getClassLoader();
public void registerCompiledSource(MemoryByteCode byteCode) {
byteCodes.put(byteCode.getClassName(), byteCode);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] bytes = byteCodeMap.get(name);
if (null != bytes) {
Class<?> ret = defineClass(name, bytes, 0, bytes.length);
byteCodeMap.remove(name);
return ret;
MemoryByteCode byteCode = byteCodes.get(name);
if (byteCode == null) {
return super.findClass(name);
}
return super.findClass(name);
return super.defineClass(name, byteCode.getByteCode(), 0, byteCode.getByteCode().length);
}
public void addByteCode(Map<String, byte[]> byteCodeMap) {
if (!CollectionUtil.isEmpty(byteCodeMap)) {
for (Map.Entry<String, byte[]> e : byteCodeMap.entrySet()) {
this.byteCodeMap.putIfAbsent(e.getKey(), e.getValue());
}
public Map<String, Class<?>> getClasses() throws ClassNotFoundException {
Map<String, Class<?>> classes = new HashMap<String, Class<?>>();
for (MemoryByteCode byteCode : byteCodes.values()) {
classes.put(byteCode.getClassName(), findClass(byteCode.getClassName()));
}
return classes;
}
public Map<String, byte[]> getByteCodes() {
Map<String, byte[]> result = new HashMap<String, byte[]>(byteCodes.size());
for (Map.Entry<String, MemoryByteCode> entry : byteCodes.entrySet()) {
result.put(entry.getKey(), entry.getValue().getByteCode());
}
return result;
}
}
@@ -21,13 +21,9 @@
*/
package fun.asgc.neutrino.core.aop.compiler;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.*;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
*
@@ -35,25 +31,112 @@ import java.util.Map;
* @date: 2022/8/17
*/
public class DynamicJavaFileManager extends ForwardingJavaFileManager<JavaFileManager> {
public Map<String, CharSequenceJavaFileObject> fileObjects = new HashMap<>();
private static final String[] superLocationNames = { StandardLocation.PLATFORM_CLASS_PATH.name(),
/** JPMS StandardLocation.SYSTEM_MODULES **/
"SYSTEM_MODULES" };
private final PackageInternalsFinder finder;
private final DynamicClassLoader classLoader;
private final List<MemoryByteCode> byteCodes = new ArrayList<MemoryByteCode>();
public DynamicJavaFileManager(JavaFileManager fileManager) {
public DynamicJavaFileManager(JavaFileManager fileManager, DynamicClassLoader classLoader) {
super(fileManager);
this.classLoader = classLoader;
this.finder = new PackageInternalsFinder(classLoader);
}
@Override
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String qualifiedClassName, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
CharSequenceJavaFileObject javaFileObject = new CharSequenceJavaFileObject(qualifiedClassName, kind);
this.fileObjects.put(qualifiedClassName, javaFileObject);
return javaFileObject;
}
public JavaFileObject getJavaFileForOutput(JavaFileManager.Location location, String className,
JavaFileObject.Kind kind, FileObject sibling) throws IOException {
for (MemoryByteCode byteCode : byteCodes) {
if (byteCode.getClassName().equals(className)) {
return byteCode;
}
}
MemoryByteCode innerClass = new MemoryByteCode(className);
byteCodes.add(innerClass);
classLoader.registerCompiledSource(innerClass);
return innerClass;
}
@Override
public JavaFileObject getJavaFileForInput(JavaFileManager.Location location, String className, JavaFileObject.Kind kind) throws IOException {
JavaFileObject javaFileObject = fileObjects.get(className);
if (javaFileObject == null) {
javaFileObject = super.getJavaFileForInput(location, className, kind);
public ClassLoader getClassLoader(JavaFileManager.Location location) {
return classLoader;
}
@Override
public String inferBinaryName(Location location, JavaFileObject file) {
if (file instanceof CustomJavaFileObject) {
return ((CustomJavaFileObject) file).binaryName();
} else {
/**
* if it's not CustomJavaFileObject, then it's coming from standard file manager
* - let it handle the file
*/
return super.inferBinaryName(location, file);
}
}
@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds,
boolean recurse) throws IOException {
if (location instanceof StandardLocation) {
String locationName = ((StandardLocation) location).name();
for (String name : superLocationNames) {
if (name.equals(locationName)) {
return super.list(location, packageName, kinds, recurse);
}
}
}
// merge JavaFileObjects from specified ClassLoader
if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) {
return new IterableJoin<JavaFileObject>(super.list(location, packageName, kinds, recurse),
finder.find(packageName));
}
return super.list(location, packageName, kinds, recurse);
}
static class IterableJoin<T> implements Iterable<T> {
private final Iterable<T> first, next;
public IterableJoin(Iterable<T> first, Iterable<T> next) {
this.first = first;
this.next = next;
}
@Override
public Iterator<T> iterator() {
return new IteratorJoin<T>(first.iterator(), next.iterator());
}
}
static class IteratorJoin<T> implements Iterator<T> {
private final Iterator<T> first, next;
public IteratorJoin(Iterator<T> first, Iterator<T> next) {
this.first = first;
this.next = next;
}
@Override
public boolean hasNext() {
return first.hasNext() || next.hasNext();
}
@Override
public T next() {
if (first.hasNext()) {
return first.next();
}
return next.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException("remove");
}
return javaFileObject;
}
}
@@ -21,57 +21,53 @@
*/
package fun.asgc.neutrino.core.aop.compiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
/**
*
* @author: aoshiguchen
* @date: 2022/8/17
* @date: 2022/8/25
*/
class CharSequenceJavaFileObject extends SimpleJavaFileObject {
private final CharSequence sourceCode;
private ByteArrayOutputStream out;
public class MemoryByteCode extends SimpleJavaFileObject {
private static final char PKG_SEPARATOR = '.';
private static final char DIR_SEPARATOR = '/';
private static final String CLASS_FILE_SUFFIX = ".class";
public CharSequenceJavaFileObject(URI uri, Kind kind) {
super(uri, kind);
this.sourceCode = null;
private ByteArrayOutputStream byteArrayOutputStream;
public MemoryByteCode(String className) {
super(URI.create("byte:///" + className.replace(PKG_SEPARATOR, DIR_SEPARATOR)
+ Kind.CLASS.extension), Kind.CLASS);
}
public CharSequenceJavaFileObject(String name, String source) {
super(URI.create(name + JavaFileObject.Kind.SOURCE.extension), JavaFileObject.Kind.SOURCE);
this.sourceCode = source;
}
public CharSequenceJavaFileObject(String name, JavaFileObject.Kind kind) {
super(URI.create(name + kind.extension), kind);
this.sourceCode = null;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
if (this.sourceCode == null) {
throw new IllegalStateException("源代码不能为空!");
}
return sourceCode;
public MemoryByteCode(String className, ByteArrayOutputStream byteArrayOutputStream)
throws URISyntaxException {
this(className);
this.byteArrayOutputStream = byteArrayOutputStream;
}
@Override
public OutputStream openOutputStream() throws IOException {
if (null == out) {
this.out = new ByteArrayOutputStream();
if (byteArrayOutputStream == null) {
byteArrayOutputStream = new ByteArrayOutputStream();
}
return out;
return byteArrayOutputStream;
}
public byte[] getByteCode() {
if (null == out) {
return null;
}
return out.toByteArray();
return byteArrayOutputStream.toByteArray();
}
public String getClassName() {
String className = getName();
className = className.replace(DIR_SEPARATOR, PKG_SEPARATOR);
className = className.substring(1, className.indexOf(CLASS_FILE_SUFFIX));
return className;
}
}
@@ -0,0 +1,130 @@
/**
* Copyright (c) 2022 aoshiguchen
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package fun.asgc.neutrino.core.aop.compiler;
import javax.tools.JavaFileObject;
import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
/**
*
* @author: aoshiguchen
* @date: 2022/8/25
*/
public class PackageInternalsFinder {
private final ClassLoader classLoader;
private static final String CLASS_FILE_EXTENSION = ".class";
public PackageInternalsFinder(ClassLoader classLoader) {
this.classLoader = classLoader;
}
public List<JavaFileObject> find(String packageName) throws IOException {
String javaPackageName = packageName.replaceAll("\\.", "/");
List<JavaFileObject> result = new ArrayList<>();
Enumeration<URL> urlEnumeration = classLoader.getResources(javaPackageName);
while (urlEnumeration.hasMoreElements()) { // one URL for each jar on the classpath that has the given package
URL packageFolderURL = urlEnumeration.nextElement();
result.addAll(listUnder(packageName, packageFolderURL));
}
return result;
}
private Collection<JavaFileObject> listUnder(String packageName, URL packageFolderURL) {
File directory = new File(decode(packageFolderURL.getFile()));
if (directory.isDirectory()) { // browse local .class files - useful for local execution
return processDir(packageName, directory);
} else { // browse a jar file
return processJar(packageFolderURL);
} // maybe there can be something else for more involved class loaders
}
private List<JavaFileObject> processJar(URL packageFolderURL) {
List<JavaFileObject> result = new ArrayList<JavaFileObject>();
try {
String jarUri = packageFolderURL.toExternalForm().substring(0, packageFolderURL.toExternalForm().lastIndexOf("!/"));
JarURLConnection jarConn = (JarURLConnection) packageFolderURL.openConnection();
String rootEntryName = jarConn.getEntryName();
int rootEnd = rootEntryName.length() + 1;
Enumeration<JarEntry> entryEnum = jarConn.getJarFile().entries();
while (entryEnum.hasMoreElements()) {
JarEntry jarEntry = entryEnum.nextElement();
String name = jarEntry.getName();
if (name.startsWith(rootEntryName) && name.indexOf('/', rootEnd) == -1 && name.endsWith(CLASS_FILE_EXTENSION)) {
URI uri = URI.create(jarUri + "!/" + name);
String binaryName = name.replaceAll("/", ".");
binaryName = binaryName.replaceAll(CLASS_FILE_EXTENSION + "$", "");
result.add(new CustomJavaFileObject(binaryName, uri));
}
}
} catch (Exception e) {
throw new RuntimeException("Wasn't able to open " + packageFolderURL + " as a jar file", e);
}
return result;
}
private List<JavaFileObject> processDir(String packageName, File directory) {
List<JavaFileObject> result = new ArrayList<JavaFileObject>();
File[] childFiles = directory.listFiles();
if (childFiles != null) {
for (File childFile : childFiles) {
if (childFile.isFile()) {
// We only want the .class files.
if (childFile.getName().endsWith(CLASS_FILE_EXTENSION)) {
String binaryName = packageName + "." + childFile.getName();
binaryName = binaryName.replaceAll(CLASS_FILE_EXTENSION + "$", "");
result.add(new CustomJavaFileObject(binaryName, childFile.toURI()));
}
}
}
}
return result;
}
private String decode(String filePath) {
try {
return URLDecoder.decode(filePath, "utf-8");
} catch (Exception e) {
// ignore, return original string
}
return filePath;
}
}
@@ -0,0 +1,46 @@
/**
* Copyright (c) 2022 aoshiguchen
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package fun.asgc.neutrino.core.aop.compiler;
import javax.tools.SimpleJavaFileObject;
import java.io.IOException;
import java.net.URI;
/**
*
* @author: aoshiguchen
* @date: 2022/8/25
*/
public class StringSource extends SimpleJavaFileObject {
private final String contents;
public StringSource(String className, String contents) {
super(URI.create("string:///" + className.replace('.', '/') + Kind.SOURCE.extension), Kind.SOURCE);
this.contents = contents;
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return contents;
}
}
@@ -43,7 +43,7 @@ public class AsgcCompilerTest {
"\t\tSystem.out.println(\"hello\");\n" +
"\t}\n" +
"}\n";
Class clazz = compiler.compileAndLoadClass("a.b","Hello", code);
Class clazz = compiler.compile("Hello", code);
Method method = ReflectUtil.getMethods(clazz).stream().filter(m -> m.getName().equals("hello")).findFirst().get();
Object instance = clazz.newInstance();
method.invoke(instance);
@@ -59,7 +59,7 @@ public class AsgcCompilerTest {
"\t\tSystem.out.println(\"熊猫正在吃\" + food);\n" +
"\t}\n" +
"}\n";
Class clazz = compiler.compileAndLoadClass("a.b","Panda", code);
Class clazz = compiler.compile("Panda", code);
Method method = ReflectUtil.getMethods(clazz).stream().filter(m -> m.getName().equals("eat")).findFirst().get();
Object instance = clazz.newInstance();
method.invoke(instance, "竹子");
@@ -76,7 +76,7 @@ public class AsgcCompilerTest {
"\t\tSystem.out.println(\"收音机播放\");\n" +
"\t}\n" +
"}\n";
Class clazz = compiler.compileAndLoadClass("a.b","RadioPlayer", code);
Class clazz = compiler.compile("RadioPlayer", code);
Method method = ReflectUtil.getMethods(clazz).stream().filter(m -> m.getName().equals("play")).findFirst().get();
Object instance = clazz.newInstance();
method.invoke(instance);
@@ -97,7 +97,7 @@ public class AsgcCompilerTest {
"\t\tSystem.out.println(\"收音机播放\");\n" +
"\t}\n" +
"}\n";
Class clazz = compiler.compileAndLoadClass("a.b","RadioPlayer", code);
Class clazz = compiler.compile("RadioPlayer", code);
Method method = ReflectUtil.getMethods(clazz).stream().filter(m -> m.getName().equals("play")).findFirst().get();
Object instance = clazz.newInstance();
method.invoke(instance);
@@ -113,7 +113,7 @@ public class AsgcCompilerTest {
"}\n";
AsgcCompiler compiler = new AsgcCompiler();
try {
Class clazz = compiler.compileAndLoadClass("fun.asgc.test", "Calc", code);
Class clazz = compiler.compile( "Calc", code);
Method method = ReflectUtil.getMethods(clazz).stream().filter(m -> m.getName().equals("invoke")).findFirst().get();
return method.invoke(null);
} catch (ClassNotFoundException|IllegalAccessException|InvocationTargetException e) {