// Path: library/src/main/java/com/danikula/videocache/file/FileNameGenerator.java
// public interface FileNameGenerator {
// 
//     String generate(String url);
// 
// }
// 
// Path: library/src/main/java/com/danikula/videocache/headers/EmptyHeadersInjector.java
// public class EmptyHeadersInjector implements HeaderInjector {
// 
//     @Override
//     public Map<String, String> addHeaders(String url) {
//         return new HashMap<>();
//     }
// 
// }
// 
// Path: library/src/main/java/com/danikula/videocache/headers/HeaderInjector.java
// public interface HeaderInjector {
// 
//     /**
//      * Adds headers to server's requests for corresponding url.
//      *
//      * @param url an url headers will be added for
//      * @return a map with headers, where keys are header's names, and values are header's values. {@code null} is not acceptable!
//      */
//     Map<String, String> addHeaders(String url);
// 
// }
// 
// Path: library/src/main/java/com/danikula/videocache/sourcestorage/SourceInfoStorage.java
// public interface SourceInfoStorage {
// 
//     SourceInfo get(String url);
// 
//     void put(String url, SourceInfo sourceInfo);
// 
//     void release();
// }
// 
// Path: library/src/main/java/com/danikula/videocache/sourcestorage/SourceInfoStorageFactory.java
// public class SourceInfoStorageFactory {
// 
//     public static SourceInfoStorage newSourceInfoStorage(Context context) {
//         return new DatabaseSourceInfoStorage(context);
//     }
// 
//     public static SourceInfoStorage newEmptySourceInfoStorage() {
//         return new NoSourceInfoStorage();
//     }
// }
// 
// Path: library/src/main/java/com/danikula/videocache/Preconditions.java
// public static void checkAllNotNull(Object... references) {
//     for (Object reference : references) {
//         if (reference == null) {
//             throw new NullPointerException();
//         }
//     }
// }
// 
// Path: library/src/main/java/com/danikula/videocache/Preconditions.java
// public static <T> T checkNotNull(T reference) {
//     if (reference == null) {
//         throw new NullPointerException();
//     }
//     return reference;
// }


import android.content.Context;
import android.net.Uri;
import com.danikula.videocache.file.DiskUsage;
import com.danikula.videocache.file.FileNameGenerator;
import com.danikula.videocache.file.Md5FileNameGenerator;
import com.danikula.videocache.file.TotalCountLruDiskUsage;
import com.danikula.videocache.file.TotalSizeLruDiskUsage;
import com.danikula.videocache.headers.EmptyHeadersInjector;
import com.danikula.videocache.headers.HeaderInjector;
import com.danikula.videocache.sourcestorage.SourceInfoStorage;
import com.danikula.videocache.sourcestorage.SourceInfoStorageFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.danikula.videocache.Preconditions.checkAllNotNull;
import static com.danikula.videocache.Preconditions.checkNotNull;

        @Override
        public void run() {
            startSignal.countDown();
            waitForRequest();
        }
    }

    private final class SocketProcessorRunnable implements Runnable {

        private final Socket socket;

        public SocketProcessorRunnable(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            processSocket(socket);
        }
    }

    /**
     * Builder for {@link HttpProxyCacheServer}.
     */
    public static final class Builder {

        private static final long DEFAULT_MAX_SIZE = 512 * 1024 * 1024;

        private File cacheRoot;
// Path: library/src/main/java/com/danikula/videocache/file/FileNameGenerator.java
// public interface FileNameGenerator {
// 
//     String generate(String url);
// 
// }
// 
// Path: library/src/main/java/com/danikula/videocache/headers/EmptyHeadersInjector.java
// public class EmptyHeadersInjector implements HeaderInjector {
// 
//     @Override
//     public Map<String, String> addHeaders(String url) {
//         return new HashMap<>();
//     }
// 
// }
// 
// Path: library/src/main/java/com/danikula/videocache/headers/HeaderInjector.java
// public interface HeaderInjector {
// 
//     /**
//      * Adds headers to server's requests for corresponding url.
//      *
//      * @param url an url headers will be added for
//      * @return a map with headers, where keys are header's names, and values are header's values. {@code null} is not acceptable!
//      */
//     Map<String, String> addHeaders(String url);
// 
// }
// 
// Path: library/src/main/java/com/danikula/videocache/sourcestorage/SourceInfoStorage.java
// public interface SourceInfoStorage {
// 
//     SourceInfo get(String url);
// 
//     void put(String url, SourceInfo sourceInfo);
// 
//     void release();
// }
// 
// Path: library/src/main/java/com/danikula/videocache/sourcestorage/SourceInfoStorageFactory.java
// public class SourceInfoStorageFactory {
// 
//     public static SourceInfoStorage newSourceInfoStorage(Context context) {
//         return new DatabaseSourceInfoStorage(context);
//     }
// 
//     public static SourceInfoStorage newEmptySourceInfoStorage() {
//         return new NoSourceInfoStorage();
//     }
// }
// 
// Path: library/src/main/java/com/danikula/videocache/Preconditions.java
// public static void checkAllNotNull(Object... references) {
//     for (Object reference : references) {
//         if (reference == null) {
//             throw new NullPointerException();
//         }
//     }
// }
// 
// Path: library/src/main/java/com/danikula/videocache/Preconditions.java
// public static <T> T checkNotNull(T reference) {
//     if (reference == null) {
//         throw new NullPointerException();
//     }
//     return reference;
// }


// Path: library/src/main/java/com/danikula/videocache/HttpProxyCacheServer.java
import android.content.Context;
import android.net.Uri;
import com.danikula.videocache.file.DiskUsage;
import com.danikula.videocache.file.FileNameGenerator;
import com.danikula.videocache.file.Md5FileNameGenerator;
import com.danikula.videocache.file.TotalCountLruDiskUsage;
import com.danikula.videocache.file.TotalSizeLruDiskUsage;
import com.danikula.videocache.headers.EmptyHeadersInjector;
import com.danikula.videocache.headers.HeaderInjector;
import com.danikula.videocache.sourcestorage.SourceInfoStorage;
import com.danikula.videocache.sourcestorage.SourceInfoStorageFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.danikula.videocache.Preconditions.checkAllNotNull;
import static com.danikula.videocache.Preconditions.checkNotNull;


        @Override
        public void run() {
            startSignal.countDown();
            waitForRequest();
        }
    }

    private final class SocketProcessorRunnable implements Runnable {

        private final Socket socket;

        public SocketProcessorRunnable(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            processSocket(socket);
        }
    }

    /**
     * Builder for {@link HttpProxyCacheServer}.
     */
    public static final class Builder {

        private static final long DEFAULT_MAX_SIZE = 512 * 1024 * 1024;

        private File cacheRoot;
        private FileNameGenerator fileNameGenerator;