// 
// Decompiled by Procyon v0.6.0
// 

package io.netty.bootstrap;

import java.util.Iterator;
import java.util.List;
import java.util.Comparator;
import java.util.ServiceLoader;
import java.util.ArrayList;
import java.lang.ref.WeakReference;
import java.util.Collections;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.util.Collection;
import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger;

abstract class ChannelInitializerExtensions
{
    private static final InternalLogger logger;
    private static volatile ChannelInitializerExtensions implementation;
    
    private ChannelInitializerExtensions() {
    }
    
    static ChannelInitializerExtensions getExtensions() {
        ChannelInitializerExtensions impl = ChannelInitializerExtensions.implementation;
        if (impl == null) {
            synchronized (ChannelInitializerExtensions.class) {
                impl = ChannelInitializerExtensions.implementation;
                if (impl != null) {
                    return impl;
                }
                final String extensionProp = SystemPropertyUtil.get("io.netty.bootstrap.extensions");
                ChannelInitializerExtensions.logger.debug("-Dio.netty.bootstrap.extensions: {}", extensionProp);
                if ("serviceload".equalsIgnoreCase(extensionProp)) {
                    impl = new ServiceLoadingExtensions(true);
                }
                else if ("log".equalsIgnoreCase(extensionProp)) {
                    impl = new ServiceLoadingExtensions(false);
                }
                else {
                    impl = new EmptyExtensions();
                }
                ChannelInitializerExtensions.implementation = impl;
            }
        }
        return impl;
    }
    
    abstract Collection<ChannelInitializerExtension> extensions(final ClassLoader p0);
    
    static {
        logger = InternalLoggerFactory.getInstance(ChannelInitializerExtensions.class);
    }
    
    private static final class EmptyExtensions extends ChannelInitializerExtensions
    {
        private EmptyExtensions() {
            super(null);
        }
        
        @Override
        Collection<ChannelInitializerExtension> extensions(final ClassLoader cl) {
            return (Collection<ChannelInitializerExtension>)Collections.emptyList();
        }
    }
    
    private static final class ServiceLoadingExtensions extends ChannelInitializerExtensions
    {
        private final boolean loadAndCache;
        private WeakReference<ClassLoader> classLoader;
        private Collection<ChannelInitializerExtension> extensions;
        
        ServiceLoadingExtensions(final boolean loadAndCache) {
            super(null);
            this.loadAndCache = loadAndCache;
        }
        
        @Override
        synchronized Collection<ChannelInitializerExtension> extensions(final ClassLoader cl) {
            final ClassLoader configured = (this.classLoader == null) ? null : this.classLoader.get();
            if (configured == null || configured != cl) {
                final Collection<ChannelInitializerExtension> loaded = serviceLoadExtensions(this.loadAndCache, cl);
                this.classLoader = new WeakReference<ClassLoader>(cl);
                this.extensions = (Collection<ChannelInitializerExtension>)(this.loadAndCache ? loaded : Collections.emptyList());
            }
            return this.extensions;
        }
        
        private static Collection<ChannelInitializerExtension> serviceLoadExtensions(final boolean load, final ClassLoader cl) {
            final List<ChannelInitializerExtension> extensions = new ArrayList<ChannelInitializerExtension>();
            final ServiceLoader<ChannelInitializerExtension> loader = ServiceLoader.load(ChannelInitializerExtension.class, cl);
            for (final ChannelInitializerExtension extension : loader) {
                extensions.add(extension);
            }
            if (!extensions.isEmpty()) {
                Collections.sort(extensions, new Comparator<ChannelInitializerExtension>() {
                    @Override
                    public int compare(final ChannelInitializerExtension a, final ChannelInitializerExtension b) {
                        return Double.compare(a.priority(), b.priority());
                    }
                });
                ChannelInitializerExtensions.logger.info("ServiceLoader {}(s) {}: {}", ChannelInitializerExtension.class.getSimpleName(), load ? "registered" : "detected", extensions);
                return (Collection<ChannelInitializerExtension>)Collections.unmodifiableList((List<?>)extensions);
            }
            ChannelInitializerExtensions.logger.debug("ServiceLoader {}(s) {}: []", ChannelInitializerExtension.class.getSimpleName(), load ? "registered" : "detected");
            return (Collection<ChannelInitializerExtension>)Collections.emptyList();
        }
    }
}
