package cgeo.geocaching.files;
import cgeo.geocaching.R;
import cgeo.geocaching.models.Geocache;
import cgeo.geocaching.utils.DisposableHandler;
import cgeo.geocaching.utils.TextUtils;
import android.os.Handler;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.zip.ZipEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.utils.IOUtils;
import org.apache.commons.lang3.StringUtils;
abstract class AbstractImportGpxZipThread extends AbstractImportGpxThread {
public static final String ENCODING = "cp437"; // Geocaching.com used windows cp 437 encoding
private String gpxFileName = null;
protected AbstractImportGpxZipThread(final int listId, final Handler importStepHandler, final DisposableHandler progressHandler) {
super(listId, importStepHandler, progressHandler);
}
@Override
protected Collection<Geocache> doImport(final GPXParser parser) throws IOException, ParserException {
Collection<Geocache> caches = Collections.emptySet();
// can't assume that GPX file comes before waypoint file in zip -> so we need two passes
// 1. parse GPX files
final ZipArchiveInputStream zisPass1 = new ZipArchiveInputStream(new BufferedInputStream(getInputStream()), ENCODING);
try {
int acceptedFiles = 0;
int ignoredFiles = 0;
for (ZipEntry zipEntry = zisPass1.getNextZipEntry(); zipEntry != null; zipEntry = zisPass1.getNextZipEntry()) {
gpxFileName = zipEntry.getName();
if (StringUtils.endsWithIgnoreCase(gpxFileName, GPXImporter.GPX_FILE_EXTENSION)) {
if (!StringUtils.endsWithIgnoreCase(gpxFileName, GPXImporter.WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) {
importStepHandler.sendMessage(importStepHandler.obtainMessage(GPXImporter.IMPORT_STEP_READ_FILE, R.string.gpx_import_loading_caches_with_filename, (int) zipEntry.getSize(), getSourceDisplayName()));
caches = parser.parse(new NoCloseInputStream(zisPass1), progressHandler);
acceptedFiles++;
}
} else {
ignoredFiles++;
}
}
if (ignoredFiles > 0 && acceptedFiles == 0) {
throw new ParserException("Imported ZIP does not contain a GPX file.");
}
} finally {
IOUtils.closeQuietly(zisPass1);
}
// 2. parse waypoint files
final InputStream inputStream = getInputStream();
final ZipArchiveInputStream zisPass2 = new ZipArchiveInputStream(new BufferedInputStream(inputStream), ENCODING);
try {
for (ZipEntry zipEntry = zisPass2.getNextZipEntry(); zipEntry != null; zipEntry = zisPass2.getNextZipEntry()) {
if (StringUtils.endsWithIgnoreCase(zipEntry.getName(), GPXImporter.WAYPOINTS_FILE_SUFFIX_AND_EXTENSION)) {
importStepHandler.sendMessage(importStepHandler.obtainMessage(GPXImporter.IMPORT_STEP_READ_WPT_FILE, R.string.gpx_import_loading_waypoints_with_filename, (int) zipEntry.getSize(), zipEntry.getName()));
caches = parser.parse(new NoCloseInputStream(zisPass2), progressHandler);
}
}
} finally {
IOUtils.closeQuietly(zisPass2);
IOUtils.closeQuietly(inputStream);
}
return caches;
}
@Override
protected String getSourceDisplayName() {
return gpxFileName == null ? ".gpx" : TextUtils.stripHtml(gpxFileName);
}
protected abstract InputStream getInputStream() throws IOException;
}