/*
This file is part of RouteConverter.
RouteConverter is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
RouteConverter is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with RouteConverter; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Copyright (C) 2007 Christian Pesch. All Rights Reserved.
*/
package slash.navigation.download.actions;
import slash.navigation.download.Download;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import static java.lang.Integer.MAX_VALUE;
import static java.lang.String.format;
import static java.util.logging.Logger.getLogger;
import static org.apache.commons.io.IOUtils.closeQuietly;
import static slash.common.io.Directories.ensureDirectory;
import static slash.common.io.Files.lastPathFragment;
import static slash.common.io.Files.setLastModified;
import static slash.common.type.CompactCalendar.fromMillis;
/**
* Extracts a {@link Download} to a target directory.
*
* @author Christian Pesch
*/
public class Extractor {
private static final Logger log = getLogger(Extractor.class.getName());
private final CopierListener listener;
public Extractor(CopierListener listener) {
this.listener = listener;
}
private void doExtract(File tempFile, File destination, boolean flatten) throws IOException {
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(tempFile))) {
ZipEntry entry = zipInputStream.getNextEntry();
while (entry != null) {
if (entry.isDirectory()) {
if (!flatten) {
File directory = new File(destination, entry.getName());
handleDirectory(directory, entry);
}
} else {
File extracted;
if(flatten)
extracted = new File(destination, lastPathFragment(entry.getName(), MAX_VALUE));
else {
extracted = new File(destination, entry.getName());
}
File directory = extracted.getParentFile();
handleDirectory(directory, entry);
log.info(format("Extracting from %s to %s", tempFile, extracted));
FileOutputStream output = new FileOutputStream(extracted);
new Copier(listener).copy(zipInputStream, output, 0, entry.getSize());
// do not close zip input stream
closeQuietly(output);
setLastModified(extracted, fromMillis(entry.getTime()));
zipInputStream.closeEntry();
}
entry = zipInputStream.getNextEntry();
}
}
}
private void handleDirectory(File directory, ZipEntry entry) throws IOException {
ensureDirectory(directory.getPath());
setLastModified(directory, fromMillis(entry.getTime()));
}
public void flatten(File tempFile, File destination) throws IOException {
doExtract(tempFile, destination, true);
}
public void extract(File tempFile, File destination) throws IOException {
doExtract(tempFile, destination, false);
}
}