package de.skuzzle.tinyplugz.internal;

import java.util.Iterator;
import java.util.ServiceLoader;

import de.skuzzle.tinyplugz.Options;
import de.skuzzle.tinyplugz.util.ElementIterator;
import de.skuzzle.tinyplugz.util.ReflectionUtil;
import de.skuzzle.tinyplugz.util.Require;

/**
 * Internal strategy interface for abstracting loading of services.
 *
 * @author Simon Taddiken
 * @since 0.3.0
 */
public abstract class ServiceLoaderWrapper {

    private static volatile ServiceLoaderWrapper defaultImpl =
            new ServiceLoaderWrapperImpl();

    /**
     * Gets the default ServiceLoaderWrapper instance.
     *
     * @return The default instance.
     */
    public static ServiceLoaderWrapper getDefault() {
        return defaultImpl;
    }

    /**
     * Restores the default implementation.
     */
    public static void restore() {
        defaultImpl = new ServiceLoaderWrapperImpl();
    }

    /**
     * Sets the source from which ServiceLoaderWrapper instances are created by
     * {@link #getDefault()}. The given object may either be a String or
     * {@link Class} object denoting a full qualified name of a class extending
     * ServiceLoaderWrapper, or it may already be an instance of
     * ServiceLoaderWrapper.
     * <p>
     * Exchanging the service loader implementation might not have an immediate
     * effect as most TinyPlugz implementations will obtain the loader during
     * their initialization. Therefore it should be exchanged before TinyPlugz
     * is deployed.
     *
     * @param source The source to obtain a ServiceLoaderWrapper from.
     * @see ReflectionUtil#createInstance(Object, Class, ClassLoader)
     * @deprecated Use of this method is unnecessary. Use
     *             {@link Options#SERVICE_LOADER_WRAPPER} instead for specifying
     *             a service loader implementation.
     */
    @Deprecated
    public static void setSource(Object source) {
        Require.nonNull(source, "source");
        final ClassLoader cl = ServiceLoaderWrapper.class.getClassLoader();
        defaultImpl = ReflectionUtil.createInstance(source,
                ServiceLoaderWrapper.class, cl);
    }

    /**
     * Returns an {@link Iterator} of all implementors of the given service
     * provider interface.
     *
     * @param <T> Type of the service provider interface.
     * @param providerClass The service provider interface.
     * @param classLoader The Classloader to use.
     * @return An iterator of implementors.
     */
    public abstract <T> ElementIterator<T> loadService(Class<T> providerClass,
            ClassLoader classLoader);

    private static final class ServiceLoaderWrapperImpl extends ServiceLoaderWrapper {

        @Override
        public <T> ElementIterator<T> loadService(Class<T> providerClass,
                ClassLoader classLoader) {
            return ElementIterator.wrap(
                    ServiceLoader.load(providerClass, classLoader).iterator());
        }

    }
}

@@ -125,156 +125,28 @@
 ugz.
-Options;%0Aimport de.skuzzle.tinyplugz.util.ElementIterator;%0Aimport de.skuzzle.tinyplugz.util.ReflectionUtil;%0Aimport de.skuzzle.tinyplugz.util.Require
+util.ElementIterator
 ;%0A%0A/
@@ -334,16 +334,13 @@
 tic 
-volatile
+final
  Ser
@@ -357,27 +357,23 @@
 Wrapper 
-defaultImpl
+DEFAULT
  =%0A     
@@ -600,1426 +600,15 @@
 urn 
-defaultImpl;%0A    %7D%0A%0A    /**%0A     * Restores the default implementation.%0A     */%0A    public static void restore() %7B%0A        defaultImpl = new ServiceLoaderWrapperImpl();%0A    %7D%0A%0A    /**%0A     * Sets the source from which ServiceLoaderWrapper instances are created by%0A     * %7B@link #getDefault()%7D. The given object may either be a String or%0A     * %7B@link Class%7D object denoting a full qualified name of a class extending%0A     * ServiceLoaderWrapper, or it may already be an instance of%0A     * ServiceLoaderWrapper.%0A     * %3Cp%3E%0A     * Exchanging the service loader implementation might not have an immediate%0A     * effect as most TinyPlugz implementations will obtain the loader during%0A     * their initialization. Therefore it should be exchanged before TinyPlugz%0A     * is deployed.%0A     *%0A     * @param source The source to obtain a ServiceLoaderWrapper from.%0A     * @see ReflectionUtil#createInstance(Object, Class, ClassLoader)%0A     * @deprecated Use of this method is unnecessary. Use%0A     *             %7B@link Options#SERVICE_LOADER_WRAPPER%7D instead for specifying%0A     *             a service loader implementation.%0A     */%0A    @Deprecated%0A    public static void setSource(Object source) %7B%0A        Require.nonNull(source, %22source%22);%0A        final ClassLoader cl = ServiceLoaderWrapper.class.getClassLoader();%0A        defaultImpl = ReflectionUtil.createInstance(source,%0A                ServiceLoaderWrapper.class, cl)
+DEFAULT
 ;%0A  

Remove unused method