

package compiler;

import com.yihu.hos.core.file.FileUtil;

import javax.tools.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 *  java编译工具类
 * @author HZY
 * @vsrsion 1.0
 * Created at 2016/11/17.
 */
public class JavaCompilerUtil {

    private static String packagePathTemplate = System.getProperty("user.dir")//获取到项目的根路径
            + "/hos-camel/src/main/java/";
    private static String classPathTemplate = System.getProperty("user.dir")//获取到项目的根路径
            + "/hos-camel/src/main/java/%s/%s.java";

    /**
     * 编译java文件
     * @param packageName     java包路径
     * @param oldClassName   旧java文件名
     * @param newClassName   新java文件名
     * @param newCron         新cron表达式
     * @throws IOException
     */
    public static void compiler(String packageName,String oldClassName,String newClassName,String newCron) throws IOException {
        String classPath = JavaCompilerUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath() ;
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // 建立DiagnosticCollector对象
        DiagnosticCollector diagnostics = new DiagnosticCollector();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
        // 建立源文件对象，每个文件被保存在一个从JavaFileObject继承的类中
        File file = genNewJava(packageName, oldClassName,newClassName, newCron);
        if (file!=null){
            Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(file.getAbsolutePath());
            // options命令行选项
            Iterable<String> options = Arrays.asList("-d",classPath);// 指定的路径一定要存在，javac不会自己创建文件夹
            JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);

            // 编译源程序
            boolean success = task.call();
            if (!success){
                List diagnostics1 = diagnostics.getDiagnostics();
                for (int i=0;i<diagnostics1.size();i++){
                    System.out.println(diagnostics1.get(i).toString());
                }
            }
            fileManager.close();
            System.out.println((success) ? "编译成功" : "编译失败");
        }


    }


    /**
     *  修改cron表达式，生成新java文件
     * @param packageName   包名
     * @param oldClassName  旧类名
     * @param newClassName  新类名
     * @param newContent    新cron表达式
     */
    public static File genNewJava(String packageName, String oldClassName,String newClassName, String newContent) {
        try {
            String oldPath = String.format(classPathTemplate, packageName, oldClassName);
            String newPath = String.format(classPathTemplate, packageName, newClassName);

            String text = FileUtil.readFileText(new File(oldPath));
            if (text.contains("?cron=")){
                String oldStr = text.substring(text.indexOf("?cron=")+6);
                String cron = oldStr.substring(0,oldStr.indexOf("\""));
                text = text.replace(cron,newContent);
            }

            if (text.contains(oldClassName)){
                text = text.replace(oldClassName,newClassName);
            }

            File f = new File(newPath);
            FileWriter fw = new FileWriter(f);
            fw.write(text);
            fw.flush();
            fw.close();//这里只是产生一个JAVA文件,简单的IO操作
            return f;
        }
        catch (Exception e) {
            System.out.println("修改操作出错");
            e.printStackTrace();
        }
        return null;
    }


    public static void compiler2(String packageName,String className) throws IOException {
        String classPath = JavaCompilerUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath() ;
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // 建立DiagnosticCollector对象
        DiagnosticCollector diagnostics = new DiagnosticCollector();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
        // 建立源文件对象，每个文件被保存在一个从JavaFileObject继承的类中
        Iterable compilationUnits = fileManager.getJavaFileObjects(String.format(classPathTemplate, packageName, className));
        // options命令行选项
        // 指定的路径一定要存在，javac不会自己创建文件夹
        Iterable<String> options = Arrays.asList(  "-d", classPath);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
        // 编译源程序
        boolean success = task.call();
        if (!success){
            List diagnostics1 = diagnostics.getDiagnostics();
            for (int i=0;i<diagnostics1.size();i++){
                System.out.println(diagnostics1.get(i).toString());
            }
        }
        fileManager.close();
        System.out.println((success) ? "编译成功" : "编译失败");
    }


    public static void testCompiler(String path,String packageName,String className) throws IOException {
        String javaPath = path+ "/%s/%s.java";
        String classPath = JavaCompilerUtil.class.getProtectionDomain().getCodeSource().getLocation().getPath() ;
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        // 建立DiagnosticCollector对象
        DiagnosticCollector diagnostics = new DiagnosticCollector();
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);
        // 建立源文件对象，每个文件被保存在一个从JavaFileObject继承的类中
        Iterable compilationUnits = fileManager.getJavaFileObjects(String.format(javaPath, packageName, className));
        // options命令行选项
        // 指定的路径一定要存在，javac不会自己创建文件夹
        Iterable<String> options = Arrays.asList(  "-d", path);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, compilationUnits);
        // 编译源程序
        boolean success = task.call();
        if (!success){
            List diagnostics1 = diagnostics.getDiagnostics();
            for (int i=0;i<diagnostics1.size();i++){
                System.out.println(diagnostics1.get(i).toString());
            }
        }
        fileManager.close();
        System.out.println((success) ? "编译成功" : "编译失败");
    }


    public static void main(String[] args) {
        try {
//            compiler("/crawler/route", "QuartzRoute","QuartzRoute001","xx000xx");
            testCompiler("D:/", "/crawler/route", "QuartzRoute");

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}
