package net.sf.openrocket.file.iterator; import java.io.File; import java.io.FileFilter; import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.sf.openrocket.util.Pair; /** * A DirectoryIterator that reads files from the specified directory of a * ZIP (or JAR) file. * * TODO: MEDIUM: This is always a recursive search. * * @author Sampo Niskanen <sampo.niskanen@iki.fi> */ public class ZipDirectoryIterator extends FileIterator { private static final Logger logger = LoggerFactory.getLogger(ZipDirectoryIterator.class); private final File zipFileName; private final String directory; private final FileFilter filter; private ZipFile zipFile; private Enumeration<? extends ZipEntry> entries; /** * Sole constructor. * * @param zipFileName the ZIP file to read. * @param directory the directory within the ZIP file to read, relative to the * base (an empty string corresponds to the root directory) * @param filter the filter for accepted files. * @throws IOException if the ZIP file could not be read. */ public ZipDirectoryIterator(File zipFileName, String directory, FileFilter filter) throws IOException { // Process directory and extension if (!directory.endsWith("/")) { directory += "/"; } this.zipFileName = zipFileName; this.directory = directory; this.filter = filter; // Loop through ZIP entries searching for files to load this.zipFile = new ZipFile(zipFileName); entries = zipFile.entries(); } @Override public void close() { super.close(); if (zipFile != null) { try { zipFile.close(); } catch (IOException e) { logger.error("Closing ZIP file failed", e); } zipFile = null; entries = null; } } @Override protected Pair<String, InputStream> findNext() { if (entries == null) { return null; } while (entries.hasMoreElements()) { ZipEntry entry = entries.nextElement(); String name = entry.getName(); File file = new File(name); if (name.startsWith(directory) && filter.accept(file)) { try { InputStream is = zipFile.getInputStream(entry); return new Pair<String, InputStream>(name, is); } catch (IOException e) { logger.error("IOException when reading ZIP file " + zipFileName, e); } } } return null; } }