Java 动态拼接代码,将字符串写入文件并编译执行。
1 拼接代码并生成文件
/*
* 文 件 名: WriteJavaFile.java
* 版 权: Sunny Technologies Co., Ltd. Copyright YYYY-YYYY, All rights reserved
* 描 述: <描述>
* 修 改 人: L.Hao
* 修改时间: 2014-11-15
* 跟踪单号: <跟踪单号>
* 修改单号: <修改单号>
* 修改内容: <修改内容>
*/
package com.fms.xx.common;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.tools.Diagnostic;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaFileObject;
import org.apache.cxf.common.util.StringUtils;
import com.fms.xx.model.ParamBean;
/**
* 写Java文件
* <功能详细描述>
*
* @author L.Hao
* @version [版本号, 2014-11-15]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
public class WriteJavaFile
{
private static String cLibfilePath; //Clibray 路径
private static String jnaUtilfilePath; //jnaUtil 路径
private static String CHFile; //h 文件路径
private static String filePath; //类路径
private static String targetDir; //编译后classes路径
private static String sourceDir;; //源目录
/**
* 生成并编译文件
* <功能详细描述>
* @param h_FilePath h文件路径
* @param projet_path 工程路径
* @return [参数说明]
*
* @return boolean [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static boolean createFileAndCompiler(String dll_FilePath, String projet_path){
CHFile = dll_FilePath.replace(".dll", ".h"); //取得H文件
List params = parseHfile(CHFile); //读取H文件
String methodName = params.get(0).getMethodName(); //方法名称
initPath(dll_FilePath,projet_path,methodName); //初始化文件路径
//创建接口文件
createFile(cLibfilePath);
//读接口CLibrary文件
String cLibraryFileContent = readFile(cLibfilePath);
//判断文件是否为空
if(StringUtils.isEmpty(cLibraryFileContent)){
String iniClibrayFileContent = spliceIniClibrayFileContent(methodName);
intWriteStringToFile(cLibfilePath, iniClibrayFileContent);
cLibraryFileContent = readFile(cLibfilePath);
}
//待拼接的内容
String appendContent = spliceCLibraryString(params);
//写文件(如果已经存在就不拼接了)
if(!cLibraryFileContent.trim().replaceAll("\\s*", "").contains(appendContent.trim().replaceAll("\\s*", ""))){
WriteStringToFile(cLibfilePath, cLibraryFileContent, appendContent);
}
//创建实现类文件
createFile(jnaUtilfilePath);
//读接口JNAUtil文件
String jNAUtilFileContent = readFile(jnaUtilfilePath);
//判断文件是否为空
if(StringUtils.isEmpty(jNAUtilFileContent)){
String iniJnaUtilFileContent = spliceIniJnaUtilFileContent(methodName);
intWriteStringToFile(jnaUtilfilePath, iniJnaUtilFileContent);
jNAUtilFileContent = readFile(jnaUtilfilePath);
}
appendContent = spliceJNAUtilString(params);
//写文件(如果已经存在就不拼接了)
if(!jNAUtilFileContent.trim().replaceAll("\\s*", "").contains(appendContent.trim().replaceAll("\\s*", ""))){
WriteStringToFile(jnaUtilfilePath, jNAUtilFileContent, appendContent);
}
boolean result = compiler(filePath, sourceDir, targetDir);
System.out.println("编译返回Flag:"+result); //true 编译成功 false//编译失败
return result;
}
/** <一句话功能简述>
* <功能详细描述>
* @param methodName //方法名称
* @return [参数说明]
*
* @return String [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
private static String spliceIniClibrayFileContent(String methodName)
{
StringBuffer sb = new StringBuffer(" ");
sb.append(" package com.fms.xx.common; ").append("\t\n");;
sb.append(" import com.sun.jna.Library; ").append("\t\n");;
sb.append(" public interface "+methodName+"CLibraryDynamic extends Library ").append("\t\n");;
sb.append(" { ").append("\t\n");;
sb.append(" } ").append("\t\n");;
return sb.toString();
}
/** <一句话功能简述>
* <功能详细描述>
* @param methodName //方法名称
* @return [参数说明]
*
* @return String [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
private static String spliceIniJnaUtilFileContent(String methodName)
{
StringBuffer sb = new StringBuffer(" ");
sb.append(" package com.fms.xx.common; ").append("\t\n");;
sb.append(" ").append("\t\n");;
sb.append(" import java.util.Arrays; ").append("\t\n");;
sb.append(" import java.util.List; ").append("\t\n");;
// sb.append(" import com.fms.xx.model.ParamBean; ").append("\t\n");;
sb.append(" import com.sun.jna.Native; ").append("\t\n");;
sb.append(" ");
sb.append(" public class "+methodName+"JNAUtilDynamic ").append("\t\n");;
sb.append(" { ").append("\t\n");;
sb.append(" ");
sb.append(" public String filePath ; ").append("\t\n");;
sb.append(" ").append("\t\n");;
sb.append(" public "+methodName+"JNAUtilDynamic(String filePath) ").append("\t\n");;
sb.append(" { ").append("\t\n");;
sb.append(" this.filePath = filePath; ").append("\t\n");;
sb.append(" } ").append("\t\n");;
sb.append(" ").append("\t\n");;
sb.append(" } ").append("\t\n");;
return sb.toString();
}
/** 初始化文件路径
* <功能详细描述>
* @param h_FilePath
* @param projet_path
* @param methodName 方法名称
* @param abFilePath [参数说明]
*
* @return void [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
private static void initPath(String h_FilePath, String projet_path, String methodName)
{
//当前ClassPath的绝对URI路径。
String abFilePath = projet_path+"WEB-INF\\classes\\com\\fms\\xx\\common"; //com.fms.xx.common
//生成文件路径
String createPath = projet_path+"WEB-INF\\classes";
System.out.println("Tomcat路径:"+projet_path);
//文件和编译路径
cLibfilePath = abFilePath+"\\"+methodName+"CLibraryDynamic.java"; //接口类
jnaUtilfilePath = abFilePath+"\\"+methodName+"JNAUtilDynamic.java"; //调用类
System.out.println("当前创建文件路径:"+cLibfilePath);
targetDir = createPath;
sourceDir = abFilePath;
filePath = abFilePath;
}
/**
* 反射调用生成的文件
* <功能详细描述>
* @param parames 参数列表
* @param i_arry 计算结果
* @param dllFilePath Dll文件路径
* @param methodName 被调用的方法名称
* @return 计算结果
*
* @return double[] [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static double[] reflectCall(List parames, double[] i_arry ,String dllFilePath ,String methodName)
{
try
{
Constructor> conststr = Class.forName("com.fms.xx.common."+methodName+"JNAUtilDynamic")
.getDeclaredConstructor(new Class[] { String.class });
conststr.setAccessible(true);
Object bl = conststr.newInstance(new Object[] {dllFilePath}); //"F:\\soft\\apache-tomcat-7.0.52\\webapps\\xxcalculate\\upload\\141112212749\\SharedLib.dll"
Class extends Object> clazz = bl.getClass();
Method method = clazz.getDeclaredMethod(methodName,
List.class,
double[].class);
method.invoke(bl, parames, i_arry);
System.out.println("计算结果:" + Arrays.toString(i_arry));
}
catch (Exception e)
{
e.printStackTrace();
}
return i_arry;
}
/**
* 创建单个文件
* <功能详细描述>
* @param filePath 文件路径
* @return [参数说明]
*
* @return boolean [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static boolean createFile(String filePath)
{
File file = new File(filePath);
if (file.exists())
{// 判断文件是否存在
System.out.println("目标文件已存在" + filePath);
//file.delete();
return true;
}
if (filePath.endsWith(File.separator))
{// 判断文件是否为目录
System.out.println("目标文件不能为目录!");
return false;
}
if (!file.getParentFile().exists())
{// 判断目标文件所在的目录是否存在
// 如果目标文件所在的文件夹不存在,则创建父文件夹
System.out.println("目标文件所在目录不存在,准备创建它!");
if (!file.getParentFile().mkdirs())
{// 判断创建目录是否成功
System.out.println("创建目标文件所在的目录失败!");
return false;
}
}
try
{
if (file.createNewFile())
{// 创建目标文件
System.out.println("创建文件成功:" + filePath);
return true;
}
else
{
System.out.println("创建文件失败!");
return false;
}
}
catch (IOException e)
{// 捕获异常
e.printStackTrace();
System.out.println("创建文件失败!" + e.getMessage());
return false;
}
}
/**
* 读取指定文件的内容
* 将指定文件的内容读入到StringBuffer中
* @param filePath
* @return [参数说明]
*
* @return String [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static String readFile(String filePath)
{
File file = new File(filePath);
BufferedReader reader = null;
StringBuffer sb = new StringBuffer();
try
{
//System.out.println("以行为单位读取文件内容,一次读一整行:");
reader = new BufferedReader(new FileReader(file));
String tempString = null;
//int line = 1;
// 一次读入一行,直到读入null为文件结束
while ((tempString = reader.readLine()) != null)
{
sb.append(tempString).append("\t\n");
}
reader.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return sb.toString();
}
/**
* 初始化字符串
* <功能详细描述>
* @param filePath
* @param content [参数说明]
*
* @return void [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static void intWriteStringToFile(String filePath,String content)
{
try
{
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
FileWriter writer = new FileWriter(filePath, false);
writer.write(content);
writer.flush(); //刷新文件
writer.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 将字符串写入指定文件
* 在已有文件内容的基础上写入新内容
* @param filePath 文件路径
* @param oldContent 已有内容
* @param newContent 新加内容
*
* @return void [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static void WriteStringToFile(String filePath, String oldContent,
String newContent)
{
StringBuffer strBuffer = new StringBuffer();
try
{
oldContent = oldContent.substring(0, oldContent.lastIndexOf("}"));
strBuffer.append(oldContent);
strBuffer.append(newContent);
strBuffer.append("}");
// 打开一个写文件器,构造函数中的第二个参数true表示以追加形式写文件
FileWriter writer = new FileWriter(filePath, false);
writer.write(strBuffer.toString());
writer.flush(); //刷新文件
writer.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 文件编译
* 调用java编译器编译java文件
* @param filePath 文件路径
* @param sourceDir 源文件所在目录
* @param targetDir 目标文件所在目录
*
* @return boolean [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
@SuppressWarnings("rawtypes")
public static boolean compiler(String filePath, String sourceDir,
String targetDir)
{
boolean compilerResult = false;
try
{
DiagnosticCollector diagnostics = new DiagnosticCollector();
compilerResult = DynamicCompilerUtil.compiler(filePath,
sourceDir,
targetDir,
diagnostics);
if (compilerResult)
{
System.out.println("编译成功");
}
else
{
System.out.println("编译失败");
for (Diagnostic diagnostic : diagnostics.getDiagnostics())
{
System.out.println(diagnostic.getMessage(null));
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
return compilerResult;
}
/**
* <一句话功能简述>
* <功能详细描述>
* @param fileName
* @return [参数说明]
*
* @return List [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static List parseHfile(String fileName)
{
Map> map = ReadHFile.ReadHFile(fileName);
List params = (List) map.get("params");
return params;
}
/**
* 拼接接口文件内容
* <功能详细描述>
* @param params
* @return [参数说明]
*
* @return String [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static String spliceCLibraryString(List params)
{
StringBuffer strBuffer = new StringBuffer();
strBuffer.append(" public void ");
strBuffer.append(params.get(0).getMethodName()).append("(");
for (FunctionParam functionParam : params)
{
strBuffer.append(functionParam.getParamType().replace("char", "byte"))
.append(" ")
.append(functionParam.getParamName())
.append(",");
}
strBuffer.replace(strBuffer.length() - 1, strBuffer.length(), "");
strBuffer.append(");").append("\t\n");
return strBuffer.toString();
}
/**
* 拼接被调用类内容
* <功能详细描述>
* @param params
* @return [参数说明]
*
* @return String [返回类型说明]
* @exception throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
*/
public static String spliceJNAUtilString(List params)
{
String methodName = params.get(0).getMethodName();
StringBuffer strBuffer = new StringBuffer();
strBuffer.append("public double[] ");
strBuffer.append(methodName)
.append("(List parameterList, double[] arr) throws Exception")
.append("\t\n");
strBuffer.append("{").append("\t\n");
strBuffer.append(" "+methodName+"CLibraryDynamic INSTANCE = ("+methodName+"CLibraryDynamic)Native.loadLibrary(filePath,"+methodName+"CLibraryDynamic.class);")
.append("\t\n");
strBuffer.append(" int num = 0;").append("\t\n");
strBuffer.append(" INSTANCE.").append(methodName).append("(");
int count = params.size();
int num = 0;
for (FunctionParam functionParam : params)
{
num++;
if (count == num)
{
continue;
}
if ("double".equalsIgnoreCase(functionParam.getParamType()))
{
strBuffer.append(" Double.valueOf(parameterList.get(num++).toString()),")
.append("\t\n");
}
if ("char".equalsIgnoreCase(functionParam.getParamType()))
{
strBuffer.append(" parameterList.get(num++).toString().getBytes(\"GBK\"),")
.append("\t\n");
}
}
strBuffer.append(" arr);").append("\t\n");
strBuffer.append(" return arr;").append("\t\n");
strBuffer.append("}").append("\t\n");
return strBuffer.toString();
}
}
/*
* 文 件 名: DynamicCompilerUtil.java
* 版 权: Sunny Technologies Co., Ltd. Copyright YYYY-YYYY, All rights reserved
* 描 述: <描述>
* 修 改 人: L.Hao
* 修改时间: 2014-11-15
* 跟踪单号: <跟踪单号>
* 修改单号: <修改单号>
* 修改内容: <修改内容>
*/
package com.fms.xx.common;
import java.io.File;
import java.io.FileFilter;
import java.io.FilenameFilter;
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.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import org.apache.commons.lang.StringUtils;
/**
* <一句话功能简述>
* <功能详细描述>
*
* @author L.Hao
* @version [版本号, 2014-11-15]
* @see [相关类/方法]
* @since [产品/模块版本]
*/
@SuppressWarnings("all")
public class DynamicCompilerUtil {
/**
* 编译java文件
*
* @param filePath
* 文件或者目录(若为目录,自动递归编译)
* @param sourceDir
* java源文件存放目录
* @param targetDir
* 编译后class类文件存放目录
* @param diagnostics
* 存放编译过程中的错误信息
* @return
* @throws Exception
*/
public static boolean compiler(String filePath, String sourceDir, String targetDir, DiagnosticCollector diagnostics)
throws Exception {
// 获取编译器实例
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
// 获取标准文件管理器实例
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
try {
if (StringUtils.isEmpty(filePath) && StringUtils.isEmpty(sourceDir) && StringUtils.isEmpty(targetDir)) {
return false;
}
// 得到filePath目录下的所有java源文件
File sourceFile = new File(filePath);
List sourceFileList = new ArrayList();
getSourceFiles(sourceFile, sourceFileList);
// 没有java文件,直接返回
if (sourceFileList.size() == 0) {
System.out.println(filePath + "目录下查找不到任何java文件");
return false;
}
// 获取要编译的编译单元
Iterable extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(sourceFileList);
/**
* 编译选项,在编译java文件时,编译程序会自动的去寻找java文件引用的其他的java源文件或者class。 -sourcepath选项就是定义java源文件的查找目录, -classpath选项就是定义class文件的查找目录。
*/
String location_jar = sourceDir.substring(0, sourceDir.indexOf("classes"))+"lib\\jna.jar";
System.out.println("编译jar位置是:"+location_jar);
Iterable options = Arrays.asList("-d", targetDir, "-sourcepath", sourceDir,"-cp",location_jar);
CompilationTask compilationTask = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
// 运行编译任务
return compilationTask.call();
} finally {
fileManager.close();
}
}
/**
* 查找该目录下的所有的java文件
*
* @param sourceFile
* @param sourceFileList
* @throws Exception
*/
private static void getSourceFiles(File sourceFile, List sourceFileList) throws Exception {
if (sourceFile.exists() && sourceFileList != null) {// 文件或者目录必须存在
if (sourceFile.isDirectory()) {// 若file对象为目录
// 得到该目录下以.java结尾的文件或者目录
File[] childrenFiles = sourceFile.listFiles(new FileFilter() {
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return true;
} else {
String name = pathname.getName();
return name.endsWith(".java") ? true : false;
}
}
});
// 递归调用
for (File childFile : childrenFiles) {
getSourceFiles(childFile, sourceFileList);
}
} else {// 若file对象为文件
sourceFileList.add(sourceFile);
}
}
}
public static void main(String[] args) {
try {
// 编译F:\\亚信工作\\SDL文件\\sdl\\src目录下的所有java文件
String filePath = "F:\\WorkSpace\\xxcalculate\\src\\com\\test";
String sourceDir = "F:\\WorkSpace\\xxcalculate\\src\\com\\test";
String targetDir = "F:\\WorkSpace\\xxcalculate\\src\\com\\classes";
DiagnosticCollector diagnostics = new DiagnosticCollector();
boolean compilerResult = compiler(filePath, sourceDir, targetDir, diagnostics);
if (compilerResult) {
System.out.println("编译成功");
} else {
System.out.println("编译失败");
for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
// System.out.format("%s[line %d column %d]-->%s%n", diagnostic.getKind(), diagnostic.getLineNumber(),
// diagnostic.getColumnNumber(),
// diagnostic.getMessage(null));
System.out.println(diagnostic.getMessage(null));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
//开始创建jna调用接口和文件
String realPath = ContextUtil.getServletContext().getRealPath("/");
// 获取算法详细信息对象
CaleArithmeticDetail caleArithmeticDetail = caclFormula.getCaleArithmeticDetail();
// 获取头文件参数列表
String dll_filePath = realPath + caleArithmeticDetail.getFilePath();
WriteJavaFile.createFileAndCompiler(dll_filePath,realPath);