package com.vip.saturn.embed;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;

public class SaturnEmbed {
    /**
     * 递归删除目录下的所有文件及子目录下所有文件
     * @param dir 将要删除的文件目录
     * @return boolean Returns "true" if all deletions were successful.
     *                 If a deletion fails, the method stops attempting to
     *                 delete and returns "false".
     */
    private static boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i=0; i<children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空，可以删除
        return dir.delete();
    }
    
	public static void start() throws Exception{
		try{
			String saturnZip = System.getProperty("saturn.zipfile",System.getenv("SATURN_ZIP_FILE"));
			if(saturnZip != null && !saturnZip.isEmpty()){
				File zipFile = new File(saturnZip);
				File saturnHome = null;
				if(zipFile.canRead()){
					//saturnHome = zipFile.getParentFile().getAbsolutePath() + File.separator + "saturn";
					saturnHome = new File(System.getProperty("user.home") + File.separator + "saturn" );
					deleteDir(saturnHome);
					unzip(zipFile, saturnHome);
					System.setProperty("saturn.home",saturnHome.listFiles()[0].getAbsolutePath());
				}
			}
		}catch(Exception e){//NOSONAR
			e.printStackTrace();
		}
		
		String saturnHome = System.getProperty("saturn.home",System.getenv("SATURN_HOME"));
		if(saturnHome == null || saturnHome.isEmpty()){
			throw new Exception("saturn.home is not set");
		}
		if(!new File(saturnHome).isDirectory()){
			throw new Exception("saturn executor not found in "+saturnHome);
		}
		
		String namespace =  System.getProperty("saturn.app.namespace",System.getenv("SATURN_APP_NAMESPACE"));
		String executorName =  System.getProperty("saturn.app.executorName",System.getenv("SATURN_APP_EXECUTOR_NAME"));
		if(namespace == null || namespace.isEmpty()){
			throw new Exception("saturn.app.namespace is not set");
		}
		if(executorName == null || executorName.isEmpty()){
			throw new Exception("saturn.app.executorName is not set");
		}
		
		URLClassLoader executorClassLoader = new URLClassLoader(new URL[]{new File(saturnHome, "saturn-executor.jar").toURI().toURL()}, null); 
		final List<String> argList = new ArrayList<>();
		String saturnLibDir = saturnHome + System.getProperty("file.separator") + "lib";
		argList.add("-saturnLibDir");
		argList.add(saturnLibDir);

		argList.add("-namespace");
		argList.add(namespace);
		
		argList.add("-executorName");
		argList.add(executorName);

		Class<?> mainClass = executorClassLoader.loadClass("com.vip.saturn.job.executor.Main");
		Object main = mainClass.newInstance();
		Method mainMethod = mainClass.getMethod("launch", String[].class, ClassLoader.class);
		
		String[] args = new String[argList.size()];
		int i=0;
		for(String arg : argList){
			args[i] = arg;
			i++;
		}

		ClassLoader outerClassLoader = Thread.currentThread().getContextClassLoader();
		try {
			mainMethod.invoke(main, args, SaturnEmbed.class.getClassLoader());
		} finally {
			Thread.currentThread().setContextClassLoader(outerClassLoader);
		}
	}
	
	public static void unzip(File zip, File directory) throws ZipException, IOException {
		ZipFile zipFile = new ZipFile(zip);
		try {
			Enumeration<? extends ZipEntry> entries = zipFile.entries();
			while (entries.hasMoreElements()) {
				ZipEntry zipEntry = entries.nextElement();
				if (zipEntry.isDirectory()) {
					File temp = new File(directory + File.separator + zipEntry.getName());
					temp.mkdirs();
					continue;
				}
				BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(zipEntry));
				File f = new File(directory + File.separator + zipEntry.getName());
				File f_p = f.getParentFile();
				if (f_p != null && !f_p.exists()) {
					f_p.mkdirs();
				}
				BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(f));
				int len = -1;
				byte[] bs = new byte[2048];
				while ((len = bis.read(bs, 0, 2048)) != -1) {
					bos.write(bs, 0, len);
				}
				bos.flush();
				bos.close();
				bis.close();
			}
		} finally {
			zipFile.close();
		}
	}
	
}

@@ -2565,131 +2565,8 @@
 %09%7D%0D%0A
-%09%09if(executorName == null %7C%7C executorName.isEmpty())%7B%0D%0A%09%09%09throw new Exception(%22saturn.app.executorName is not set%22);%0D%0A%09%09%7D%0D%0A
 %09%09%0D%0A
@@ -2961,22 +2961,78 @@
 pace);%0D%0A
-%09%09
+%0D%0A%09%09if(executorName != null && !executorName.isEmpty()) %7B
 %0D%0A%09%09
+%09
 argList.
@@ -3048,32 +3048,33 @@
 cutorName%22);%0D%0A%09%09
+%09
 argList.add(exec
@@ -3080,24 +3080,29 @@
 cutorName);%0D
+%0A%09%09%7D%0D
 %0A%0D%0A%09%09Class%3C?

Embed start executor, the executorName could be not set #128