package org.mockito.internal.configuration.plugins;

import org.mockito.exceptions.base.MockitoException;
import org.mockito.exceptions.misusing.MockitoConfigurationException;
import org.mockito.internal.util.collections.Iterables;
import org.mockito.plugins.PluginSwitch;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

class PluginLoader {

    private final PluginSwitch pluginSwitch;

    public PluginLoader(PluginSwitch pluginSwitch) {
        this.pluginSwitch = pluginSwitch;
    }

    /**
     * Scans the classpath for given pluginType. If not found, default class is used.
     */
    <T> T loadPlugin(Class<T> pluginType, String defaultPluginClassName) {
        for (T plugin : loadImplementations(pluginType)) {
            return plugin; // return the first one service loader finds (if any)
        }

        try {
            // Default implementation. Use our own ClassLoader instead of the context
            // ClassLoader, as the default implementation is assumed to be part of
            // Mockito and may not be available via the context ClassLoader.
            return pluginType.cast(Class.forName(defaultPluginClassName).newInstance());
        } catch (Exception e) {
            throw new MockitoException("Internal problem occurred, please report it. " +
                    "Mockito is unable to load the default implementation of class that is a part of Mockito distribution. " +
                    "Failed to load " + pluginType, e);
        }
    }

    /**
     * Equivalent to {@link java.util.ServiceLoader#load} but without requiring
     * Java 6 / Android 2.3 (Gingerbread).
     */
    <T> List<T> loadImplementations(Class<T> service) {
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        if (loader == null) {
            loader = ClassLoader.getSystemClassLoader();
        }
        Enumeration<URL> resources;
        try {
            resources = loader.getResources("mockito-extensions/" + service.getName());
        } catch (IOException e) {
            throw new MockitoException("Failed to load " + service, e);
        }

        //TODO SF refactor
        List<T> result = new ArrayList<T>();
        try {
            String foundPluginClass = new PluginFinder(pluginSwitch).findPluginClass(Iterables.toIterable(resources));
            if (foundPluginClass != null) {
                Class<?> pluginClass = loader.loadClass(foundPluginClass);
                Object plugin = pluginClass.newInstance();
                result.add(service.cast(plugin));
            }
            return result;
        } catch (Exception e) {
            throw new MockitoConfigurationException(
                    "Failed to load " + service + " implementation declared in " + resources, e);
        }
    }
}

@@ -337,70 +337,19 @@
 til.
-ArrayList;%0Aimport java.util.Enumeration;%0Aimport java.util.List
+Enumeration
 ;%0A%0Ac
@@ -706,13 +706,8 @@
     
-for (
 T pl
@@ -715,9 +715,9 @@
 gin 
-:
+=
  loa
@@ -721,27 +721,16 @@
 loadImpl
-ementations
 (pluginT
@@ -733,31 +733,26 @@
 ginType)
-) %7B%0A   
+;%0A
         
  return 
@@ -747,77 +747,56 @@
     
- return plugin; // return the first one service loader finds (if any)
+if (plugin != null) %7B%0A            return plugin;
 %0A   
@@ -1620,23 +1620,17 @@
     %3CT%3E 
-List%3CT%3E
+T
  loadImp
@@ -1634,19 +1634,8 @@
 Impl
-ementations
 (Cla
@@ -2084,80 +2084,8 @@
  %7D%0A%0A
-        //TODO SF refactor%0A        List%3CT%3E result = new ArrayList%3CT%3E();%0A
     
@@ -2413,17 +2413,13 @@
   re
-sult.add(
+turn 
 serv
@@ -2434,17 +2434,16 @@
 (plugin)
-)
 ;%0A      
@@ -2473,14 +2473,12 @@
 urn 
-result
+null
 ;%0A  

simplified the code