AsgcCompiler优化,支持保存生成的源码、class文件。
This commit is contained in:
@@ -24,6 +24,7 @@ package fun.asgc.neutrino.core.aop.compiler;
|
||||
import com.google.common.collect.Lists;
|
||||
import fun.asgc.neutrino.core.base.GlobalConfig;
|
||||
import fun.asgc.neutrino.core.util.CollectionUtil;
|
||||
import fun.asgc.neutrino.core.util.FileUtil;
|
||||
import fun.asgc.neutrino.core.util.SystemUtil;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -78,6 +79,9 @@ public class AsgcCompiler {
|
||||
}
|
||||
|
||||
public void addClasspath(String classpath) {
|
||||
if (this.classpathList.contains(classpath)) {
|
||||
return;
|
||||
}
|
||||
this.classpathList.add(classpath);
|
||||
}
|
||||
|
||||
@@ -128,7 +132,15 @@ public class AsgcCompiler {
|
||||
public Class<?> compile(String pkg, String className, String sourceCode) throws ClassNotFoundException {
|
||||
log.info("options:" + getOptions());
|
||||
JavaFileManager javaFileManager = new DynamicJavaFileManager(standardJavaFileManager, dynamicClassLoader);
|
||||
Boolean result = javaCompiler.getTask(null, javaFileManager, collector, getOptions(), null, Lists.newArrayList(new StringSource(className, sourceCode))).call();
|
||||
Iterable<? extends JavaFileObject> compilationUnits = Lists.newArrayList(new StringSource(className, sourceCode));
|
||||
if (GlobalConfig.isSaveGeneratorCode()) {
|
||||
javaFileManager = standardJavaFileManager;
|
||||
File file = FileUtil.save(GlobalConfig.getGeneratorCodeSavePath() + pkg.replaceAll("\\.", "/"), className + ".java", sourceCode);
|
||||
compilationUnits = standardJavaFileManager.getJavaFileObjects(file);
|
||||
addClasspath(GlobalConfig.getGeneratorCodeSavePath());
|
||||
}
|
||||
|
||||
Boolean result = javaCompiler.getTask(null, javaFileManager, collector, getOptions(), null, compilationUnits).call();
|
||||
if (!result || collector.getDiagnostics().size() > 0) {
|
||||
if (!result || collector.getDiagnostics().size() > 0) {
|
||||
for (Diagnostic<? extends JavaFileObject> diagnostic : collector.getDiagnostics()) {
|
||||
|
||||
+79
-1
@@ -21,11 +21,22 @@
|
||||
*/
|
||||
package fun.asgc.neutrino.core.aop.compiler;
|
||||
|
||||
import fun.asgc.neutrino.core.base.GlobalConfig;
|
||||
import fun.asgc.neutrino.core.util.ArrayUtil;
|
||||
import fun.asgc.neutrino.core.util.ClassUtil;
|
||||
import fun.asgc.neutrino.core.util.CollectionUtil;
|
||||
import fun.asgc.neutrino.core.util.FileUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.*;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -35,6 +46,7 @@ import java.util.*;
|
||||
public class DynamicClassLoader extends ClassLoader {
|
||||
private final Map<String, MemoryByteCode> byteCodes = new HashMap<>();
|
||||
private AsgcCompiler compiler;
|
||||
private Map<String, Class<?>> classMap = new HashMap<>();
|
||||
|
||||
public DynamicClassLoader(ClassLoader classLoader) {
|
||||
super(classLoader);
|
||||
@@ -51,6 +63,9 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
||||
if (classMap.containsKey(name)) {
|
||||
return classMap.get(name);
|
||||
}
|
||||
MemoryByteCode byteCode = byteCodes.get(name);
|
||||
if (null != byteCode) {
|
||||
return super.defineClass(name, byteCode.getByteCode(), 0, byteCode.getByteCode().length);
|
||||
@@ -78,7 +93,7 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
if (path.endsWith(".jar")) {
|
||||
url = new URL("jar:file:" + path + "!/");
|
||||
}
|
||||
Set<Class<?>> classSet = ClassUtil.scan(packageName, url);
|
||||
Set<Class<?>> classSet = scan(packageName, url);
|
||||
if (CollectionUtil.isEmpty(classSet)) {
|
||||
continue;
|
||||
}
|
||||
@@ -93,6 +108,69 @@ public class DynamicClassLoader extends ClassLoader {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<Class<?>> scan(String packageName, URL url) throws IOException, ClassNotFoundException, URISyntaxException {
|
||||
Set<Class<?>> result = new HashSet<>();
|
||||
if (null == url) {
|
||||
return result;
|
||||
}
|
||||
String packagePath = packageName.replace(".", "/");
|
||||
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader());
|
||||
String protocol = url.getProtocol();
|
||||
if ("jar".equals(protocol)) {
|
||||
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
|
||||
JarFile jarFile = jarURLConnection.getJarFile();
|
||||
Enumeration<JarEntry> entries = jarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry jarEntry = entries.nextElement();
|
||||
String name = jarEntry.getName();
|
||||
int index = name.indexOf(packagePath);
|
||||
if (index != -1 && name.endsWith(".class")) {
|
||||
String replace = name.substring(index, name.length() - 6).replace("/", ".");
|
||||
Class clazz = urlClassLoader.loadClass(replace);
|
||||
result.add(clazz);
|
||||
}
|
||||
}
|
||||
} else if ("file".endsWith(protocol)) {
|
||||
String path = url.getPath();
|
||||
String targetPath = path + "/" + packagePath;
|
||||
addClasses(targetPath, result, packageName);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private synchronized void addClasses(String path, Set<Class<?>> classes, String packageName) throws ClassNotFoundException, URISyntaxException {
|
||||
File[] files = new File(path).listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
return (file.isFile() && file.getName().endsWith(".class")) || file.isDirectory();
|
||||
}
|
||||
});
|
||||
if (ArrayUtil.isEmpty(files)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (File file : files) {
|
||||
String fileName = file.getName();
|
||||
if (file.isFile()) {
|
||||
String className = fileName.substring(0, fileName.lastIndexOf("."));
|
||||
String fullClassName = packageName + "." + className;
|
||||
Class clazz = null;
|
||||
if (path.startsWith(GlobalConfig.getGeneratorCodeSavePath())) {
|
||||
byte[] byteCode = FileUtil.readBytes(file);
|
||||
clazz = super.defineClass(fullClassName, byteCode, 0, byteCode.length);
|
||||
this.classMap.put(fullClassName, clazz);
|
||||
} else {
|
||||
clazz = Thread.currentThread().getContextClassLoader().loadClass(fullClassName);
|
||||
}
|
||||
classes.add(clazz);
|
||||
} else {
|
||||
String subPackagePath = path + "/" + fileName;
|
||||
String subPackageName = packageName + "." + fileName;
|
||||
addClasses(subPackagePath, classes, subPackageName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Class<?>> getClasses() throws ClassNotFoundException {
|
||||
Map<String, Class<?>> classes = new HashMap<>();
|
||||
for (MemoryByteCode byteCode : byteCodes.values()) {
|
||||
|
||||
@@ -39,6 +39,7 @@ public class MemoryByteCode extends SimpleJavaFileObject {
|
||||
private static final String CLASS_FILE_SUFFIX = ".class";
|
||||
|
||||
private ByteArrayOutputStream byteArrayOutputStream;
|
||||
private byte[] byteCode;
|
||||
|
||||
public MemoryByteCode(String className) {
|
||||
super(URI.create("byte:///" + className.replace(PKG_SEPARATOR, DIR_SEPARATOR)
|
||||
@@ -51,6 +52,12 @@ public class MemoryByteCode extends SimpleJavaFileObject {
|
||||
this.byteArrayOutputStream = byteArrayOutputStream;
|
||||
}
|
||||
|
||||
public MemoryByteCode(String className, byte[] byteCode)
|
||||
throws URISyntaxException {
|
||||
this(className);
|
||||
this.byteCode = byteCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream openOutputStream() throws IOException {
|
||||
if (byteArrayOutputStream == null) {
|
||||
@@ -60,7 +67,7 @@ public class MemoryByteCode extends SimpleJavaFileObject {
|
||||
}
|
||||
|
||||
public byte[] getByteCode() {
|
||||
return byteArrayOutputStream.toByteArray();
|
||||
return null == byteCode ? byteArrayOutputStream.toByteArray() : byteCode;
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
|
||||
@@ -111,18 +111,30 @@ public class FileUtil {
|
||||
*/
|
||||
public static byte[] readBytes(String path) {
|
||||
try (InputStream in = getInputStream(path)){
|
||||
byte[] bytes = new byte[1024];
|
||||
int length = 0;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
while ((length = in.read(bytes)) != -1) {
|
||||
baos.write(bytes, 0, length);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
return readBytes(in);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] readBytes(File file) {
|
||||
try (InputStream in = new FileInputStream(file)){
|
||||
return readBytes(in);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] readBytes(InputStream in) throws IOException {
|
||||
byte[] bytes = new byte[1024];
|
||||
int length = 0;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
while ((length = in.read(bytes)) != -1) {
|
||||
baos.write(bytes, 0, length);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public static void write(String path, String content) {
|
||||
// try (BufferedWriter writer = Files.newBufferedWriter(Paths.get(path), StandardCharsets.UTF_8)){
|
||||
// writer.write(content);
|
||||
|
||||
@@ -24,6 +24,7 @@ package fun.asgc.neutrino.proxy.server;
|
||||
|
||||
import fun.asgc.neutrino.core.annotation.EnableJob;
|
||||
import fun.asgc.neutrino.core.annotation.NeutrinoApplication;
|
||||
import fun.asgc.neutrino.core.base.GlobalConfig;
|
||||
import fun.asgc.neutrino.core.context.NeutrinoLauncher;
|
||||
|
||||
/**
|
||||
@@ -36,6 +37,7 @@ import fun.asgc.neutrino.core.context.NeutrinoLauncher;
|
||||
public class ProxyServer {
|
||||
|
||||
public static void main(String[] args) {
|
||||
GlobalConfig.setIsSaveGeneratorCode(true);
|
||||
NeutrinoLauncher.run(ProxyServer.class, args).sync();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user