package org.xbib.io.archive; import org.xbib.io.BytesProgressWatcher; import org.xbib.io.compress.CompressCodecService; import java.nio.file.Path; import java.util.Map; import java.util.ServiceLoader; import java.util.Set; import java.util.WeakHashMap; public class ArchiveService { private final static Map<String, ArchiveCodec> archiveCodecs = new WeakHashMap<String, ArchiveCodec>(); private final static Set<String> codecs = CompressCodecService.getCodecs(); private final static ArchiveService instance = new ArchiveService(); private ArchiveService() { ServiceLoader<ArchiveCodec> loader = ServiceLoader.load(ArchiveCodec.class, getClass().getClassLoader()); for (ArchiveCodec codec : loader) { if (!archiveCodecs.containsKey(codec.getName())) { archiveCodecs.put(codec.getName(), codec); } } } public static ArchiveService getInstance() { return instance; } public ArchiveCodec getCodec(String name) { if (archiveCodecs.containsKey(name)) { return archiveCodecs.get(name); } throw new IllegalArgumentException("archive codec for " + name + " not found in " + archiveCodecs); } public static Set<String> getCodecs() { return archiveCodecs.keySet(); } @SuppressWarnings("unchecked") public static <I extends ArchiveInputStream, O extends ArchiveOutputStream> ArchiveSession<I, O> newSession(Path path, BytesProgressWatcher watcher) { for (String archiverName : getCodecs()) { if (canOpen(archiverName, path)) { return archiveCodecs.get(archiverName).newSession(watcher); } } throw new IllegalArgumentException("no archive session implementation found for path " + path); } private static boolean canOpen(String suffix, Path path) { String pathStr = path.toString(); if (pathStr.endsWith("." + suffix.toLowerCase()) || pathStr.endsWith("." + suffix.toUpperCase())) { return true; } for (String codec : codecs) { String s = "." + suffix + "." + codec; if (pathStr.endsWith(s) || pathStr.endsWith(s.toLowerCase()) || pathStr.endsWith(s.toUpperCase())) { return true; } } return false; } }