package com.lambdaworks.redis;

import static com.google.common.base.Preconditions.checkState;

import java.lang.reflect.Constructor;
import java.net.SocketAddress;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadFactory;

import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

/**
 * Wraps and provides Epoll classes. This is to protect the user from {@link ClassNotFoundException}'s caused by the absence of
 * the {@literal netty-transport-native-epoll} library during runtime. Internal API.
 * 
 * @author Mark Paluch
 */
public class EpollProvider {

    protected static final InternalLogger logger = InternalLoggerFactory.getInstance(EpollProvider.class);

    public final static Class<EventLoopGroup> epollEventLoopGroupClass;
    public final static Class<Channel> epollDomainSocketChannelClass;
    public final static Class<SocketAddress> domainSocketAddressClass;
    static {

        epollEventLoopGroupClass = getClass("io.netty.channel.epoll.EpollEventLoopGroup");
        epollDomainSocketChannelClass = getClass("io.netty.channel.epoll.EpollDomainSocketChannel");
        domainSocketAddressClass = getClass("io.netty.channel.unix.DomainSocketAddress");
        if (epollDomainSocketChannelClass == null || epollEventLoopGroupClass == null) {
            logger.debug("Starting without optional Epoll library");
        }
    }

    /**
     * Try to load class {@literal className}.
     * 
     * @param className
     * @param <T> Expected return type for casting.
     * @return instance of {@literal className} or null
     */
    private static <T> Class<T> getClass(String className) {
        try {
            return (Class) JavaRuntime.forName(className);
        } catch (ClassNotFoundException e) {
            logger.debug("Cannot load class " + className, e);
        }
        return null;
    }

    /**
     * Check whether the Epoll library is available on the class path.
     * 
     * @throws IllegalStateException if the {@literal netty-transport-native-epoll} library is not available
     * 
     */
    static void checkForEpollLibrary() {

        checkState(domainSocketAddressClass != null && epollDomainSocketChannelClass != null,
                "Cannot connect using sockets without the optional netty-transport-native-epoll library on the class path");
    }

    static SocketAddress newSocketAddress(String socketPath) {
        return get(() -> {
            Constructor<SocketAddress> constructor = domainSocketAddressClass.getConstructor(String.class);
            return constructor.newInstance(socketPath);
        });
    }

    public static EventLoopGroup newEventLoopGroup(int nThreads, ThreadFactory threadFactory) {

        try {
            Constructor<EventLoopGroup> constructor = epollEventLoopGroupClass
                    .getConstructor(Integer.TYPE, ThreadFactory.class);
            return constructor.newInstance(nThreads, threadFactory);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }

    private static <V> V get(Callable<V> supplier) {
        try {
            return supplier.call();
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
    }
}

@@ -1024,24 +1024,25 @@
 dressClass;%0A
+%0A
     static %7B
@@ -1760,24 +1760,358 @@
 lassName) %7B%0A
+%0A        // Maven Shade plugin also transforms strings containg class names so we%0A        // need to revert that here.%0A        String unShadedClassName = className;%0A        String prefix = %22com.lambdaworks.%22;%0A        if (className.startsWith(prefix)) %7B%0A            unShadedClassName = className.substring(prefix.length());%0A        %7D%0A%0A
         try 
@@ -2159,17 +2159,25 @@
 forName(
-c
+unShadedC
 lassName
@@ -2272,17 +2272,25 @@
 ass %22 + 
-c
+unShadedC
 lassName
@@ -3279,29 +3279,8 @@
 lass
-%0A                    
 .get
@@ -3304,16 +3304,36 @@
 er.TYPE,
+%0A                   
  ThreadF

Remove shading prefix when using Epoll #230