/*
* Copyright (C) 2005-2015 Schlichtherle IT Services.
* All rights reserved. Use is subject to license terms.
*/
package net.java.truevfs.access;
import java.io.File;
import java.net.URISyntaxException;
import java.util.*;
import java.util.Map.Entry;
import javax.annotation.CheckForNull;
import javax.annotation.concurrent.Immutable;
import javax.inject.Provider;
import net.java.truecommons.services.Loader;
import net.java.truecommons.shed.ExtensionSet;
import net.java.truecommons.shed.HashMaps;
import static net.java.truecommons.shed.HashMaps.initialCapacity;
import net.java.truevfs.kernel.spec.FsAbstractCompositeDriver;
import net.java.truevfs.kernel.spec.FsDriver;
import net.java.truevfs.kernel.spec.FsScheme;
import net.java.truevfs.kernel.spec.sl.FsDriverMapLocator;
/**
* Detects a prospective archive file and declares its file system
* scheme by mapping its file name extension to an archive driver.
* Note that this class does not access any file system!
*
* The map of detectable archive file name extensions and corresponding archive
* drivers is configured by the constructors of this class.
* There are two types of constructors available:
*
* - Constructors which filter the driver map of a given file system driver
* provider by a given list of file name extensions.
* For example, the driver map of the provider
* {@link FsDriverMapLocator#SINGLETON} could be filtered by the file name
* extension list {@code "tar|zip"} in order to recognize only TAR and ZIP
* files.
*
- Constructors which decorate a given file system driver provider with a
* given map of file system schemes to file system drivers.
* This can get used to specify custom archive file name extensions or
* archive drivers.
* For example, the file name extension list {@code "foo|bar"} could be used
* to detect a custom variant of the JAR file format (you need to provide
* a custom archive driver then, too).
*
*
* Where a constructor expects a list of file name extensions as a parameter,
* it must obeye the syntax constraints for {@link ExtensionSet}s.
* As an example, the parameter {@code "zip|jar"} would cause
* the archive detector to recognize ZIP and JAR files in a path.
* The same would be true for {@code "||.ZiP||.JaR||ZIP||JAR||"},
* but this notation is discouraged because it's not in canonical form.
*
* @author Christian Schlichtherle
*/
@Immutable
public final class TArchiveDetector extends FsAbstractCompositeDriver {
/**
* This instance never recognizes any archive files in a path.
* This can get used as the end of a chain of
* {@code TArchiveDetector} instances or if archive files
* shall be treated like regular files rather than (virtual) directories.
*/
public static final TArchiveDetector NULL = new TArchiveDetector("");
/**
* This instance recognizes all archive file name extensions for which an
* archive driver can get located on the class path by the file system
* driver map locator singleton {@link FsDriverMapLocator#SINGLETON}.
*/
public static final TArchiveDetector ALL = new TArchiveDetector(null);
@SuppressWarnings("AccessingNonPublicFieldOfAnotherObject")
private static ExtensionSet extensions(
final Provider