package net.northking.cctp.dataPool.utils;

import net.northking.cctp.dataPool.constants.DataPoolConstant;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author zhengbang.jiang
 * @date 2021/1/12
 * @since 1.0
 */
public class MyUrlClassLoader extends URLClassLoader {

    private List<JarURLConnection> cachedJarFiles = new ArrayList<>();

    private List<File> jarFiles = new ArrayList<>();

    private static final Logger logger = LoggerFactory.getLogger(MyUrlClassLoader.class);

    public MyUrlClassLoader() {
        super(new URL[]{}, findParentClassLoader());
    }

    private static ClassLoader findParentClassLoader() {
        ClassLoader parent = net.northking.cctp.dataPool.utils.MyUrlClassLoader.class.getClassLoader();
        if (parent == null) {
            parent = net.northking.cctp.dataPool.utils.MyUrlClassLoader.getSystemClassLoader();
        }
        return parent;
    }

    public void addURLFile(File f) throws MalformedURLException {
        jarFiles.add(f);
        String jarStr = "jar:" + f.toURI().toURL().toExternalForm() + "!/";
        URL file = new URL(jarStr);
        try {
            URLConnection uc = file.openConnection();
            if (uc instanceof JarURLConnection) {
                uc.setUseCaches(true);
                ((JarURLConnection) uc).getManifest();
                cachedJarFiles.add((JarURLConnection) uc);
                Method method = URLClassLoader.class.getDeclaredMethod(DataPoolConstant.ADD_URL, URL.class);
                URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
                boolean accessible = method.isAccessible();
                try {
                    if (!accessible) {
                        method.setAccessible(true);
                    }
                    URL url1 = file.toURI().toURL();
                    method.invoke(classLoader, url1);
                } catch (IllegalAccessException e) {
                    logger.error("",e);
                } catch (MalformedURLException e) {
                    logger.error("",e);
                } catch (InvocationTargetException e) {
                    logger.error("",e);
                } finally {
                    method.setAccessible(accessible);
                }
            }
        } catch (Exception e) {
            logger.error("",e);
        }
    }

    public void unloadJarFiles() {
        List<JarURLConnection> list = new ArrayList<>();
        for (JarURLConnection url : cachedJarFiles) {
            try {
                list.add(url);
                url.getJarFile().close();
                url = null;
            } catch (Exception e) {
                logger.error("",e);
            }
        }
        cachedJarFiles.removeAll(list);
        list = null;
        for (File jarFile : jarFiles) {
            boolean delete = jarFile.delete();
            if (!delete) {
                logger.error("删除文件失败");
            }
        }
    }

}
