package com.izforge.izpack.merge.resolve;

import com.izforge.izpack.api.exception.MergeException;
import com.izforge.izpack.api.merge.Mergeable;
import com.izforge.izpack.merge.ClassResolver;

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;

/**
 * Crawl and store a map of all files in classpath when we can't get package directly
 *
 * @author Anthonin Bonnefoy
 */
public class ClassPathCrawler
{

    private MergeableResolver mergeableResolver;
    private HashMap<String, List<URL>> classPathContentCache;

    public ClassPathCrawler(MergeableResolver mergeableResolver)
    {
        this.mergeableResolver = mergeableResolver;
    }


    public String getCurrentClasspath()
    {
        StringBuilder stringBuilder = new StringBuilder();
        for (URL url : getClassPathUrl())
        {
            stringBuilder.append(url.getPath());
            stringBuilder.append('\n');
        }
        return stringBuilder.toString();
    }

    public void processClassPath()
    {
        if (classPathContentCache != null)
        {
            return;
        }
        classPathContentCache = new HashMap<String, List<URL>>();
        try
        {
            Collection<URL> urls = getClassPathUrl();
            for (URL url : urls)
            {
                Mergeable mergeable = mergeableResolver.getMergeableFromURL(url);
                final List<File> files = mergeable.recursivelyListFiles(new FileFilter()
                {
                    public boolean accept(File pathname)
                    {
                        return true;
                    }
                });
                if (files != null)
                {
                    for (File file : files)
                    {
                        getOrCreateList(classPathContentCache, file.getName()).add(file.toURI().toURL());
                    }
                }
            }
        }
        catch (Exception e)
        {
            throw new MergeException(e);
        }
    }

    private List<URL> getOrCreateList(HashMap<String, List<URL>> classPathContentCache, String key)
    {
        if (!classPathContentCache.containsKey(key))
        {
            classPathContentCache.put(key, new ArrayList<URL>());
        }
        return classPathContentCache.get(key);
    }

    public Class searchClassInClassPath(final String className)
    {
        try
        {
            final String fileToSearch = className + ".class";
            processClassPath();
            List<URL> urlList = classPathContentCache.get(fileToSearch);
            if (urlList != null)
            {
                String fullClassName = ClassResolver.processURLToClassName(urlList.get(0));
                return Class.forName(fullClassName);
            }
        }
        catch (ClassNotFoundException ignored)
        {
        }
        throw new MergeException("Could not find class " + className + " : Current classpath is " + getCurrentClasspath());
    }


    public List<URL> searchPackageInClassPath(final String packageName)
    {
        processClassPath();
        return classPathContentCache.get(packageName);
    }

    private Collection<URL> getClassPathUrl()
    {
        Collection<URL> result = new HashSet<URL>();
        java.net.URLClassLoader loader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
        result.addAll(Arrays.asList(loader.getURLs()));
        try
        {
            Enumeration<URL> urlEnumeration = loader.getResources("");
            result.addAll(Collections.list(urlEnumeration));
            urlEnumeration = loader.getResources("META-INF/");
            result.addAll(Collections.list(urlEnumeration));
        }
        catch (IOException ignored)
        {
        }
        return result;
    }

}

@@ -606,16 +606,241 @@
 ntCache;
+%0A    private static final List%3CString%3E excludedJar = Arrays.asList(%22alt-rt.jar%22, %22rt.jar%22, %22charsets.jar%22, %22deploy.jar%22,%0A            %22javaws.jar%22, %22jce.jar%22, %22jsse.jar%22, %22management-agent.jar%22, %22plugin.jar%22, %22resources.jar%22);
 %0A%0A    pu
@@ -3991,32 +3991,84 @@
 lEnumeration));%0A
+            removeExcludedJar(result, excludedJar);%0A
         %7D%0A      
@@ -4147,10 +4147,438 @@
 %0A    %7D%0A%0A
+%0A    private void removeExcludedJar(Collection%3CURL%3E result, List%3CString%3E excludedJar)%0A    %7B%0A        HashSet%3CURL%3E toRemove = new HashSet%3CURL%3E();%0A        for (URL url : result)%0A        %7B%0A            for (String s : excludedJar)%0A            %7B%0A                if (url.getPath().contains(s))%0A                %7B%0A                    toRemove.add(url);%0A                %7D%0A            %7D%0A        %7D%0A        result.removeAll(toRemove);%0A    %7D%0A
 %7D%0A

Exclude jar from crawling