package cn.baiweigang.qtaf.toolkit.util;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
/**
* 编译java文件为class
* @author @<a href='http://weibo.com/bwgang'>bwgang</a><br/>
*
*/
public class CompilerUtil {
//日志记录
private static LogUtil log=LogUtil.getLogger(CompilerUtil.class);
/**
* 编译java文件为class
* @param javaFilePath java文件或包含java文件的目录
* @param distPath 项目class文件存放目录
* @param libPath jar包存放目录
* @param jarFile jar包存放目录(maven)
* @return boolean 编译成功返回true
*/
public static boolean dynamicCompiler(String javaFilePath,String distPath,String libPath,String jarFile) {
DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
boolean compilerResult = compiler("UTF-8",getClassPath(libPath,distPath,jarFile),javaFilePath, distPath, diagnostics);
if (compilerResult) {
// log.info("编译:"+javaFilePath+" 文件或目录成功,输出目录为:"+distPath);
}else{
log.info("编译失败");
for (@SuppressWarnings("rawtypes") Diagnostic diagnostic : diagnostics.getDiagnostics()) {
log.error(diagnostic.getMessage(null));
}
}
return compilerResult;
}
/**
* 编译java文件
* @param encoding 编译编码
* @param jars 需要加载的jar目录或文件
* @param filePath 文件或者目录(若为目录,编译目录下所有java文件)
* @param sourceDir 项目源码目录
* @param distDir 编译后class类文件存放目录
* @param diagnostics 存放编译过程中的错误信息
* @return boolean
*/
private static boolean compiler(String encoding,String jars,String filePath, String distDir, DiagnosticCollector<JavaFileObject> diagnostics){
// 获取编译器实例
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// 获取标准文件管理器实例
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
//编译文件
if (StringUtil.IsNullOrEmpty(filePath)) {
log.info("待编译的文件或目录不存在");
return false;
}
//输出目录
if (!FileUtil.createDictory(distDir)) {
log.info("输出目录创建失败");
return false;
}
// 得到filePath目录下的所有java源文件
File sourceFile = new File(filePath);
List<File> sourceFileList = new ArrayList<File>();
sourceFileList = getSourceFiles(sourceFile);
// 没有java文件,直接返回
if (sourceFileList.size() == 0) {
log.info(filePath + "目录下查找不到任何java文件");
return false;
}
// 获取要编译的编译单元
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
//编译选项,在编译java文件时,编译程序会自动的去寻找java文件引用的其他的java源文件或者class。 -classpath选项就是定义class文件的查找目录。
Iterable<String> options = Arrays.asList("-encoding",encoding,"-classpath",jars,"-d", distDir);
CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
// 运行编译任务
boolean res= compilationTask.call();
try {
fileManager.close();
} catch (IOException e) {
log.error("关闭文件管理器失败");
log.error(e.getMessage());
}
return res;
}
/**
* 查找该目录下的所有的java文件
* @param sourceFile
* @return List<File>
*/
private static List<File> getSourceFiles(File sourceFile){
List<File> sourceFileList = new ArrayList<File>();
if (sourceFile.exists() && sourceFileList != null) {//文件或者目录必须存在
if (sourceFile.isDirectory()) {// 若file对象为目录
// 得到该目录下以.java结尾的所有文件
List<String> sourceFileListTmp=FileUtil.getFilesFromFolder(sourceFile.getPath(),"java");
for (String filePath : sourceFileListTmp) {
sourceFileList.add(new File(filePath));
}
} else {// 若file对象为文件
sourceFileList.add(sourceFile);
}
}else{
log.info("目录或文件不存在: "+sourceFile);
}
return sourceFileList;
}
/**
* 查找该目录下的所有的jar文件
* @param libPath
* @return String
*/
private static String getJarFiles(String libPath,String jarFile) {
// 得到该目录下以.jar结尾的所有文件
String jarsPath="";
List<String> jarFilePath = FileUtil.getFilesFromFolder(libPath,"jar");
for (String filePath : jarFilePath) {
jarsPath=jarsPath+filePath+";";
}
jarsPath=jarsPath+jarFile;
return jarsPath;
}
private static String getClassPath(String libPath,String classPath,String jarFile){
if (FileUtil.isEmeyxist(classPath)) {
return getJarFiles(libPath,jarFile)+classPath;
}else{
log.info("classPath不存在:"+classPath);
return getJarFiles(libPath,jarFile);
}
}
}