package org.sfm.utils;

import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

public class LibrarySetsClassLoader extends URLClassLoader {
    private final ClassLoader classLoader;
    private final String[] libraries;
    private final Pattern[] excludes;

    public LibrarySetsClassLoader(ClassLoader classLoader, String[] libraries, Class<?>[] includes, Pattern[] excludes) throws IOException {
        super(getUrls(libraries, includes), Integer.class.getClassLoader());
        this.classLoader = classLoader;
        this.libraries = libraries;
        this.excludes = excludes;
    }

    private static URL[] getUrls(String[] libraries, Class<?>[] includes) throws IOException {
        List<URL> urls = new ArrayList<URL>();

        for(int i = 0; i < libraries.length; i++) {
            urls.add(new URL(libraries[i]));
        }

        for(Class<?> includeClass : includes) {
            URL url = findUrl(includeClass, includeClass.getClassLoader());
            if (!urls.contains(url)) {
                urls.add(url);
            }
        }

        return urls.toArray(new URL[0]);


    }

    private static URL findUrl(Class<?> includeClass, ClassLoader classLoader) {
        if (classLoader instanceof URLClassLoader) {
            for(URL url : ((URLClassLoader)classLoader).getURLs()) {
                if (urlContains(url, includeClass)) {
                    return url;
                }
            }
        }

        ClassLoader parent = classLoader.getParent();
        if (parent != null) {
            return findUrl(includeClass, parent);
        }
        throw new IllegalArgumentException("Could not find url for " + includeClass);
    }


    private static boolean urlContains(URL url, Class<?> includeClass) {
        URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url});
        return urlClassLoader.findResource(includeClass.getName().replace(".", "/") + ".class") != null;
    }

    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        if (isExcluded(name)) {
            return classLoader.loadClass(name);
        }
        try {
            return super.loadClass(name);
        } catch (ClassNotFoundException e) {
            return classLoader.loadClass(name);
        }
    }

    private boolean isExcluded(String name) {
        for(Pattern p : excludes) {
            if(p.matcher(name).find()) {
                return true;
            }
        }
        return false;
    }

    @Override
    public String toString() {
        return "LibrarySetsClassLoader{" +
                "libraries=" + Arrays.toString(libraries) +
                '}';
    }
}

@@ -45,16 +45,55 @@
 eption;%0A
+import java.net.MalformedURLException;%0A
 import j
@@ -1365,106 +1365,147 @@
 er) 
-%7B%0A        if (classLoader instanceof URLClassLoader) %7B%0A            for(URL url : ((URLClassLoader)
+throws MalformedURLException %7B%0A%0A        String classResource = includeClass.getName().replace(%22.%22, %22/%22) + %22.class%22;%0A        URL urlClass = 
 clas
@@ -1515,149 +1515,252 @@
 ader
-)
 .get
-URLs()) %7B%0A                if (urlContains(url, includeClass)) %7B%0A                    return url;%0A                %7D%0A      
+Resource(classResource);%0A%0A        if (urlClass != null) %7B%0A            String url = urlClass.toString();%0A%0A            if (url.startsWith(%22jar:%22)) %7B%0A                int bang = url.indexOf('!');%0A                if (bang != -1) %7B%0A
       
-%7D%0A
         
 %7D%0A%0A 
@@ -1759,62 +1759,65 @@
     
-%7D%0A%0A
       
-  ClassLoader parent = classLoader.getParent(
+String jarUrl = url.substring(%22jar:%22.length(), bang
 );%0A 
@@ -1827,330 +1827,445 @@
     
+ 
-if (parent != null) %7B%0A            return findUrl(includeClass, parent);%0A        %7D%0A        throw new IllegalArgumentException(%22Could not find url for %22 + includeClass);%0A    %7D%0A%0A%0A    private static boolean urlContains(URL url, Class%3C?%3E includeClass) %7B%0A        URLClassLoader urlClassLoader = new URLClassLoader(new URL%5B%5D%7Bu
+           System.out.println(%22jarUrl = %22 + jarUrl);%0A                    return new URL(jarUrl);%0A                %7D%0A            %7D else if (url.startsWith(%22file:%22)) %7B%0A                if (url.endsWith(classResource)) %7B%0A                    String directoryUrl = url.substring(0, url.length() - classResource.length());%0A                    System.out.println(%22directoryUrl = %22 + directoryUrl);%0A                    return new URL(directoryU
 rl
-%7D
 );%0A 
@@ -2275,103 +2275,144 @@
     
+    
-return urlClassLoader.findResource(includeClass.getName().replace(%22.%22, %22/%22) + %22.class%22) != null
+    %7D%0A            %7D%0A        %7D%0A%0A        throw new IllegalArgumentException(%22Could not find url for %22 + includeClass + %22 %22 + urlClass)
 ;%0A  

fix url discovery to not introspect classloader