Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/OdPlugin.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/OdPlugin.java	(revision 29679)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/OdPlugin.java	(revision 29680)
@@ -51,4 +51,5 @@
 import org.openstreetmap.josm.plugins.opendata.core.io.AbstractImporter;
 import org.openstreetmap.josm.plugins.opendata.core.io.XmlImporter;
+import org.openstreetmap.josm.plugins.opendata.core.io.archive.SevenZipImporter;
 import org.openstreetmap.josm.plugins.opendata.core.io.archive.ZipImporter;
 import org.openstreetmap.josm.plugins.opendata.core.io.geographic.GmlImporter;
@@ -86,5 +87,6 @@
 				new CsvImporter(), new OdsImporter(), new XlsImporter(), // Tabular file formats
 				new KmlKmzImporter(), new ShpImporter(), new MifTabImporter(), new GmlImporter(), // Geographic file formats
-				new ZipImporter(), // Archive containing any of the others
+				new ZipImporter(), // Zip archive containing any of the others
+                new SevenZipImporter(), // 7Zip archive containing any of the others
 				xmlImporter // Generic importer for XML files (currently used for Neptune files)
 		})) {
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/OdConstants.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/OdConstants.java	(revision 29679)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/OdConstants.java	(revision 29680)
@@ -104,4 +104,5 @@
     public static final String MAPCSS_EXT = "mapcss";
     public static final String ZIP_EXT = "zip";
+    public static final String SEVENZIP_EXT = "7z";
     public static final String JAR_EXT = "jar";
     public static final String XML_EXT = "xml";
@@ -124,4 +125,5 @@
     public static final ExtensionFileFilter GML_FILE_FILTER = new ExtensionFileFilter(GML_EXT, GML_EXT, tr("GML files") + " (*."+GML_EXT+")");
     public static final ExtensionFileFilter ZIP_FILE_FILTER = new ExtensionFileFilter(ZIP_EXT, ZIP_EXT, tr("Zip Files") + " (*."+ZIP_EXT+")");
+    public static final ExtensionFileFilter SEVENZIP_FILE_FILTER = new ExtensionFileFilter(SEVENZIP_EXT, SEVENZIP_EXT, tr("7Zip Files") + " (*."+SEVENZIP_EXT+")");
     public static final ExtensionFileFilter XML_FILE_FILTER = new ExtensionFileFilter(XML_EXT, XML_EXT, tr("OpenData XML files") + " (*."+XML_EXT+")");
     
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/datasets/AbstractDataSetHandler.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/datasets/AbstractDataSetHandler.java	(revision 29679)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/datasets/AbstractDataSetHandler.java	(revision 29680)
@@ -35,6 +35,6 @@
 import org.openstreetmap.josm.io.AbstractReader;
 import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
-import org.openstreetmap.josm.plugins.opendata.core.io.archive.DefaultZipHandler;
-import org.openstreetmap.josm.plugins.opendata.core.io.archive.ZipHandler;
+import org.openstreetmap.josm.plugins.opendata.core.io.archive.DefaultArchiveHandler;
+import org.openstreetmap.josm.plugins.opendata.core.io.archive.ArchiveHandler;
 import org.openstreetmap.josm.plugins.opendata.core.io.geographic.DefaultGmlHandler;
 import org.openstreetmap.josm.plugins.opendata.core.io.geographic.DefaultShpHandler;
@@ -92,5 +92,5 @@
 	public AbstractDataSetHandler() {
 		setShpHandler(new DefaultShpHandler());
-		setZipHandler(new DefaultZipHandler());
+		setArchiveHandler(new DefaultArchiveHandler());
 		setCsvHandler(new DefaultCsvHandler());
 		setGmlHandler(new DefaultGmlHandler());
@@ -460,14 +460,14 @@
 	}
 
-	// ------------ Zip handling ------------
-	
-	private ZipHandler zipHandler;
-
-	public final void setZipHandler(ZipHandler handler) {
-		zipHandler = handler;
-	}
-	
-	public ZipHandler getZipHandler() {
-		return zipHandler;
+	// ------------ Archive handling ------------
+	
+	private ArchiveHandler archiveHandler;
+
+	public final void setArchiveHandler(ArchiveHandler handler) {
+		archiveHandler = handler;
+	}
+	
+	public ArchiveHandler getArchiveHandler() {
+		return archiveHandler;
 	}
 	
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ArchiveHandler.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ArchiveHandler.java	(revision 29680)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ArchiveHandler.java	(revision 29680)
@@ -0,0 +1,27 @@
+//    JOSM opendata plugin.
+//    Copyright (C) 2011-2013 Don-vip
+//
+//    This program 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 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.opendata.core.io.archive;
+
+import java.io.File;
+
+public interface ArchiveHandler {
+
+	public void notifyTempFileWritten(File file);
+
+	public boolean skipXsdValidation();
+
+	public void setSkipXsdValidation(boolean skip);
+}
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ArchiveReader.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ArchiveReader.java	(revision 29680)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ArchiveReader.java	(revision 29680)
@@ -0,0 +1,172 @@
+//    JOSM opendata plugin.
+//    Copyright (C) 2011-2013 Don-vip
+//
+//    This program 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 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.opendata.core.io.archive;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamException;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.AbstractReader;
+import org.openstreetmap.josm.plugins.opendata.OdPlugin;
+import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
+import org.openstreetmap.josm.plugins.opendata.core.datasets.AbstractDataSetHandler;
+import org.openstreetmap.josm.plugins.opendata.core.gui.DialogPrompter;
+import org.openstreetmap.josm.plugins.opendata.core.io.NeptuneReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.geographic.GmlReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.geographic.KmlReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.geographic.KmzReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.geographic.MifReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.geographic.ShpReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.geographic.TabReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.tabular.CsvReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.tabular.OdsReader;
+import org.openstreetmap.josm.plugins.opendata.core.io.tabular.XlsReader;
+import org.openstreetmap.josm.plugins.opendata.core.util.OdUtils;
+
+public abstract class ArchiveReader extends AbstractReader implements OdConstants {
+
+    protected final AbstractDataSetHandler handler;
+    protected final ArchiveHandler archiveHandler;
+    protected final boolean promptUser;
+
+    private File file;
+
+    public ArchiveReader(AbstractDataSetHandler handler, ArchiveHandler archiveHandler, boolean promptUser) {
+        this.handler = handler;
+        this.archiveHandler = archiveHandler;
+        this.promptUser = promptUser;
+    }
+    
+    public final File getReadFile() {
+        return file;
+    }
+    
+    protected abstract void extractArchive(final File temp, final List<File> candidates) throws IOException, FileNotFoundException;
+    
+    protected abstract String getTaskMessage();
+        
+    public DataSet parseDoc(final ProgressMonitor progressMonitor) throws IOException, XMLStreamException, FactoryConfigurationError, JAXBException  {
+        
+        final File temp = OdUtils.createTempDir();
+        final List<File> candidates = new ArrayList<File>();
+        
+        try {
+            if (progressMonitor != null) {
+                progressMonitor.beginTask(getTaskMessage());
+            }
+            extractArchive(temp, candidates);
+            
+            file = null;
+            
+            if (promptUser && candidates.size() > 1) {
+                DialogPrompter<CandidateChooser> prompt = new DialogPrompter() {
+                    @Override
+                    protected CandidateChooser buildDialog() {
+                        return new CandidateChooser(progressMonitor.getWindowParent(), candidates);
+                    }
+                };
+                if (prompt.promptInEdt().getValue() == 1) {
+                    file = prompt.getDialog().getSelectedFile();
+                }
+            } else if (!candidates.isEmpty()) {
+                file = candidates.get(0);
+            }
+            
+            if (file == null) {
+                return null;
+            } else if (!file.exists()) {
+                Main.warn("File does not exist: "+file.getPath());
+                return null;
+            } else {
+                DataSet from = null;
+                FileInputStream in = new FileInputStream(file);
+                ProgressMonitor instance = null;
+                if (progressMonitor != null) {
+                    instance = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
+                }
+                if (file.getName().toLowerCase().endsWith(CSV_EXT)) {
+                    from = CsvReader.parseDataSet(in, handler, instance);
+                } else if (file.getName().toLowerCase().endsWith(KML_EXT)) {
+                    from = KmlReader.parseDataSet(in, instance);
+                } else if (file.getName().toLowerCase().endsWith(KMZ_EXT)) {
+                    from = KmzReader.parseDataSet(in, instance);
+                } else if (file.getName().toLowerCase().endsWith(XLS_EXT)) {
+                    from = XlsReader.parseDataSet(in, handler, instance);
+                } else if (file.getName().toLowerCase().endsWith(ODS_EXT)) {
+                    from = OdsReader.parseDataSet(in, handler, instance);
+                } else if (file.getName().toLowerCase().endsWith(SHP_EXT)) {
+                    from = ShpReader.parseDataSet(in, file, handler, instance);
+                } else if (file.getName().toLowerCase().endsWith(MIF_EXT)) {
+                    from = MifReader.parseDataSet(in, file, handler, instance);
+                } else if (file.getName().toLowerCase().endsWith(TAB_EXT)) {
+                    from = TabReader.parseDataSet(in, file, handler, instance);
+                } else if (file.getName().toLowerCase().endsWith(GML_EXT)) {
+                    from = GmlReader.parseDataSet(in, handler, instance);
+                } else if (file.getName().toLowerCase().endsWith(XML_EXT)) {
+                    if (OdPlugin.getInstance().xmlImporter.acceptFile(file)) {
+                        from = NeptuneReader.parseDataSet(in, handler, instance);
+                    } else {
+                        System.err.println("Unsupported XML file: "+file.getName());
+                    }
+                    
+                } else {
+                    System.err.println("Unsupported file extension: "+file.getName());
+                }
+                if (from != null) {
+                    ds = from;
+                }
+            }
+        } catch (IllegalArgumentException e) {
+            System.err.println(e.getMessage());
+        } finally {
+            OdUtils.deleteDir(temp);
+            if (progressMonitor != null) {
+                progressMonitor.finishTask();
+            }
+        }
+        
+        return ds;
+    }
+
+    protected final void lookForCandidate(String entryName, final List<File> candidates, File file) {
+        // Test file name to see if it may contain useful data
+        for (String ext : new String[] {
+                CSV_EXT, KML_EXT, KMZ_EXT, XLS_EXT, ODS_EXT, SHP_EXT, MIF_EXT, TAB_EXT, GML_EXT
+        }) {
+            if (entryName.toLowerCase().endsWith("."+ext)) {
+                candidates.add(file);
+                System.out.println(entryName);
+                break;
+            }
+        }
+        // Special treatment for XML files (check supported XSD), unless handler explicitely skip it
+        if (XML_FILE_FILTER.accept(file) && ((archiveHandler != null && archiveHandler.skipXsdValidation()) 
+                || OdPlugin.getInstance().xmlImporter.acceptFile(file))) {
+            candidates.add(file);
+            System.out.println(entryName);
+        }
+    }
+}
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/DefaultArchiveHandler.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/DefaultArchiveHandler.java	(revision 29680)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/DefaultArchiveHandler.java	(revision 29680)
@@ -0,0 +1,38 @@
+//    JOSM opendata plugin.
+//    Copyright (C) 2011-2013 Don-vip
+//
+//    This program 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 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.opendata.core.io.archive;
+
+import java.io.File;
+
+public class DefaultArchiveHandler implements ArchiveHandler {
+
+	private boolean skipXsdValidation = false;
+	
+	@Override
+	public final void setSkipXsdValidation(boolean skip) {
+		skipXsdValidation = skip;
+	}
+	
+	@Override
+	public boolean skipXsdValidation() {
+		return skipXsdValidation;
+	}
+	
+	@Override
+	public void notifyTempFileWritten(File file) {
+		// Do nothing, let subclass override this method if they need it
+	}
+}
Index: plications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/DefaultZipHandler.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/DefaultZipHandler.java	(revision 29679)
+++ 	(revision )
@@ -1,38 +1,0 @@
-//    JOSM opendata plugin.
-//    Copyright (C) 2011-2012 Don-vip
-//
-//    This program 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 3 of the License, or
-//    (at your option) any later version.
-//
-//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-package org.openstreetmap.josm.plugins.opendata.core.io.archive;
-
-import java.io.File;
-
-public class DefaultZipHandler implements ZipHandler {
-
-	private boolean skipXsdValidation = false;
-	
-	@Override
-	public final void setSkipXsdValidation(boolean skip) {
-		skipXsdValidation = skip;
-	}
-	
-	@Override
-	public boolean skipXsdValidation() {
-		return skipXsdValidation;
-	}
-	
-	@Override
-	public void notifyTempFileWritten(File file) {
-		// Do nothing, let subclass override this method if they need it
-	}
-}
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/SevenZipImporter.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/SevenZipImporter.java	(revision 29680)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/SevenZipImporter.java	(revision 29680)
@@ -0,0 +1,40 @@
+//    JOSM opendata plugin.
+//    Copyright (C) 2011-2013 Don-vip
+//
+//    This program 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 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.opendata.core.io.archive;
+
+import java.io.InputStream;
+
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.IllegalDataException;
+import org.openstreetmap.josm.plugins.opendata.core.io.AbstractImporter;
+
+public class SevenZipImporter extends AbstractImporter {
+
+	public SevenZipImporter() {
+		super(SEVENZIP_FILE_FILTER);
+	}
+
+	@Override
+	protected DataSet parseDataSet(InputStream in, ProgressMonitor instance)
+			throws IllegalDataException {
+		try {
+			return SevenZipReader.parseDataSet(in, handler, instance, true);
+		} catch (Exception e) {
+			throw new IllegalDataException(e);
+		}
+	}
+}
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/SevenZipReader.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/SevenZipReader.java	(revision 29680)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/SevenZipReader.java	(revision 29680)
@@ -0,0 +1,105 @@
+//    JOSM opendata plugin.
+//    Copyright (C) 2011-2013 Don-vip
+//
+//    This program 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 3 of the License, or
+//    (at your option) any later version.
+//
+//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
+package org.openstreetmap.josm.plugins.opendata.core.io.archive;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.stream.FactoryConfigurationError;
+import javax.xml.stream.XMLStreamException;
+
+import org.j7zip.SevenZip.ArchiveExtractCallback;
+import org.j7zip.SevenZip.HRESULT;
+import org.j7zip.SevenZip.IInStream;
+import org.j7zip.SevenZip.MyRandomAccessFile;
+import org.j7zip.SevenZip.Archive.IInArchive;
+import org.j7zip.SevenZip.Archive.SevenZip.Handler;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.plugins.opendata.core.datasets.AbstractDataSetHandler;
+import org.openstreetmap.josm.plugins.opendata.core.util.OdUtils;
+import org.openstreetmap.josm.tools.Utils;
+
+public class SevenZipReader extends ArchiveReader {
+
+    private final IInArchive archive = new Handler();
+    
+    public SevenZipReader(InputStream in, AbstractDataSetHandler handler, boolean promptUser) throws IOException {
+        super(handler, handler != null ? handler.getArchiveHandler() : null, promptUser);
+        OutputStream out = null;
+        try {
+            // Write entire 7z file as a temp file on disk as we need random access later, and "in" can be a network stream
+            File tmpFile = File.createTempFile("7z_", ".7z", OdUtils.createTempDir());
+            out = new FileOutputStream(tmpFile);
+            Utils.copyStream(in, out);
+            Utils.close(out);
+            out = null;
+            IInStream random = new MyRandomAccessFile(tmpFile.getPath(), "r");
+            if (archive.Open(random) != 0) {
+                String message = "Unable to open 7z archive: "+tmpFile.getPath();
+                Main.warn(message);
+                random.close();
+                if (!tmpFile.delete()) {
+                    tmpFile.deleteOnExit();
+                }
+                throw new IOException(message);
+            }
+        } finally {
+            Utils.close(out);
+        }
+    }
+    
+    public static DataSet parseDataSet(InputStream in, AbstractDataSetHandler handler, ProgressMonitor instance, boolean promptUser) 
+            throws IOException, XMLStreamException, FactoryConfigurationError, JAXBException {
+        return new SevenZipReader(in, handler, promptUser).parseDoc(instance);
+    }
+
+    @Override protected String getTaskMessage() {
+        return tr("Reading 7Zip file...");
+    }
+
+    @Override protected void extractArchive(File temp, List<File> candidates) throws IOException, FileNotFoundException {
+        archive.Extract(null, -1, IInArchive.NExtract_NAskMode_kExtract, new ExtractCallback(archive, temp, candidates));
+    }
+    
+    private class ExtractCallback extends ArchiveExtractCallback {
+        private final List<File> candidates;
+        
+        public ExtractCallback(IInArchive archive, File tempDir, List<File> candidates) {
+            Init(archive);
+            super.outputDir = tempDir.getPath();
+            this.candidates = candidates;
+        }
+
+        @Override 
+        public int GetStream(int index, OutputStream[] outStream, int askExtractMode) throws IOException {
+            int res = super.GetStream(index, outStream, askExtractMode);
+            if (res == HRESULT.S_OK) {
+                lookForCandidate(_filePath, candidates, file);
+            }
+            return res;
+        }
+    }
+}
Index: plications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ZipHandler.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ZipHandler.java	(revision 29679)
+++ 	(revision )
@@ -1,27 +1,0 @@
-//    JOSM opendata plugin.
-//    Copyright (C) 2011-2012 Don-vip
-//
-//    This program 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 3 of the License, or
-//    (at your option) any later version.
-//
-//    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
-package org.openstreetmap.josm.plugins.opendata.core.io.archive;
-
-import java.io.File;
-
-public interface ZipHandler {
-
-	public void notifyTempFileWritten(File file);
-
-	public boolean skipXsdValidation();
-
-	public void setSkipXsdValidation(boolean skip);
-}
Index: /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ZipReader.java
===================================================================
--- /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ZipReader.java	(revision 29679)
+++ /applications/editors/josm/plugins/opendata/src/org/openstreetmap/josm/plugins/opendata/core/io/archive/ZipReader.java	(revision 29680)
@@ -19,9 +19,8 @@
 
 import java.io.File;
-import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.util.ArrayList;
 import java.util.List;
 import java.util.zip.ZipEntry;
@@ -34,35 +33,15 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
-import org.openstreetmap.josm.io.AbstractReader;
-import org.openstreetmap.josm.plugins.opendata.OdPlugin;
-import org.openstreetmap.josm.plugins.opendata.core.OdConstants;
 import org.openstreetmap.josm.plugins.opendata.core.datasets.AbstractDataSetHandler;
-import org.openstreetmap.josm.plugins.opendata.core.gui.DialogPrompter;
-import org.openstreetmap.josm.plugins.opendata.core.io.NeptuneReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.geographic.GmlReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.geographic.KmlReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.geographic.KmzReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.geographic.MifReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.geographic.ShpReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.geographic.TabReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.tabular.CsvReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.tabular.OdsReader;
-import org.openstreetmap.josm.plugins.opendata.core.io.tabular.XlsReader;
-import org.openstreetmap.josm.plugins.opendata.core.util.OdUtils;
 
-public class ZipReader extends AbstractReader implements OdConstants {
+public class ZipReader extends ArchiveReader {
 
 	private final ZipInputStream zis;
-	private final AbstractDataSetHandler handler;
-	private final ZipHandler zipHandler;
-	private final boolean promptUser;
 	
-	private File file;
-    
+	private ZipEntry entry;
+	
     public ZipReader(InputStream in, AbstractDataSetHandler handler, boolean promptUser) {
+        super(handler, handler != null ? handler.getArchiveHandler() : null, promptUser);
         this.zis = in instanceof ZipInputStream ? (ZipInputStream) in : new ZipInputStream(in);
-        this.handler = handler;
-        this.zipHandler = handler != null ? handler.getZipHandler() : null;
-        this.promptUser = promptUser;
     }
 
@@ -71,137 +50,45 @@
 		return new ZipReader(in, handler, promptUser).parseDoc(instance);
 	}
-	
-	public final File getReadFile() {
-		return file;
-	}
-	
-	public DataSet parseDoc(final ProgressMonitor progressMonitor) throws IOException, XMLStreamException, FactoryConfigurationError, JAXBException  {
-		
-	    final File temp = OdUtils.createTempDir();
-	    final List<File> candidates = new ArrayList<File>();
-	    
-	    try {
-	    	if (progressMonitor != null) {
-	    		progressMonitor.beginTask(tr("Reading Zip file..."));
-	    	}
-			ZipEntry entry;
-			while ((entry = zis.getNextEntry()) != null) {
-				File file = new File(temp + File.separator + entry.getName());
-		    	File parent = file.getParentFile();
-		    	if (parent != null && !parent.exists()) {
-		    		parent.mkdirs();
-		    	}
-			    if (file.exists() && !file.delete()) {
-			        throw new IOException("Could not delete temp file/dir: " + file.getAbsolutePath());
-			    }
-			    if (!entry.isDirectory()) {
-			    	if (!file.createNewFile()) { 
-			    		throw new IOException("Could not create temp file: " + file.getAbsolutePath());
-			    	}
-			    	// Write temp file
-					FileOutputStream fos = new FileOutputStream(file);
-					byte[] buffer = new byte[8192];
-					int count = 0;
-					while ((count = zis.read(buffer, 0, buffer.length)) > 0) {
-						fos.write(buffer, 0, count);
-					}
-					fos.close();
-					// Allow handler to perform specific treatments (for example, fix invalid .prj files)
-					if (zipHandler != null) {
-						zipHandler.notifyTempFileWritten(file);
-					}
-					// Set last modification date
-					long time = entry.getTime();
-					if (time > -1) {
-						file.setLastModified(time);
-					}
-					// Test file name to see if it may contain useful data
-					for (String ext : new String[] {
-							CSV_EXT, KML_EXT, KMZ_EXT, XLS_EXT, ODS_EXT, SHP_EXT, MIF_EXT, TAB_EXT, GML_EXT
-					}) {
-						if (entry.getName().toLowerCase().endsWith("."+ext)) {
-							candidates.add(file);
-							System.out.println(entry.getName());
-							break;
-						}
-					}
-					// Special treatment for XML files (check supported XSD), unless handler explicitely skip it
-					if (XML_FILE_FILTER.accept(file) && ((zipHandler != null && zipHandler.skipXsdValidation()) 
-							|| OdPlugin.getInstance().xmlImporter.acceptFile(file))) {
-						candidates.add(file);
-						System.out.println(entry.getName());
-					}
-				} else if (!file.mkdir()) {
-					throw new IOException("Could not create temp dir: " + file.getAbsolutePath());
-				}
-			}
-			
-			file = null;
-			
-			if (promptUser && candidates.size() > 1) {
-				DialogPrompter<CandidateChooser> prompt = new DialogPrompter() {
-					@Override
-					protected CandidateChooser buildDialog() {
-						return new CandidateChooser(progressMonitor.getWindowParent(), candidates);
-					}
-				};
-				if (prompt.promptInEdt().getValue() == 1) {
-					file = prompt.getDialog().getSelectedFile();
-				}
-			} else if (!candidates.isEmpty()) {
-				file = candidates.get(0);
-			}
-			
-			if (file == null) {
-				return null;
-			} else {
-				DataSet from = null;
-				FileInputStream in = new FileInputStream(file);
-				ProgressMonitor instance = null;
-				if (progressMonitor != null) {
-					instance = progressMonitor.createSubTaskMonitor(ProgressMonitor.ALL_TICKS, false);
-				}
-				if (file.getName().toLowerCase().endsWith(CSV_EXT)) {
-					from = CsvReader.parseDataSet(in, handler, instance);
-				} else if (file.getName().toLowerCase().endsWith(KML_EXT)) {
-					from = KmlReader.parseDataSet(in, instance);
-				} else if (file.getName().toLowerCase().endsWith(KMZ_EXT)) {
-					from = KmzReader.parseDataSet(in, instance);
-				} else if (file.getName().toLowerCase().endsWith(XLS_EXT)) {
-					from = XlsReader.parseDataSet(in, handler, instance);
-				} else if (file.getName().toLowerCase().endsWith(ODS_EXT)) {
-					from = OdsReader.parseDataSet(in, handler, instance);
-				} else if (file.getName().toLowerCase().endsWith(SHP_EXT)) {
-					from = ShpReader.parseDataSet(in, file, handler, instance);
-				} else if (file.getName().toLowerCase().endsWith(MIF_EXT)) {
-					from = MifReader.parseDataSet(in, file, handler, instance);
-				} else if (file.getName().toLowerCase().endsWith(TAB_EXT)) {
-					from = TabReader.parseDataSet(in, file, handler, instance);
-				} else if (file.getName().toLowerCase().endsWith(GML_EXT)) {
-					from = GmlReader.parseDataSet(in, handler, instance);
-				} else if (file.getName().toLowerCase().endsWith(XML_EXT)) {
-					if (OdPlugin.getInstance().xmlImporter.acceptFile(file)) {
-						from = NeptuneReader.parseDataSet(in, handler, instance);
-					} else {
-						System.err.println("Unsupported XML file: "+file.getName());
-					}
-					
-				} else {
-					System.err.println("Unsupported file extension: "+file.getName());
-				}
-				if (from != null) {
-					ds = from;
-				}
-			}
-	    } catch (IllegalArgumentException e) {
-	    	System.err.println(e.getMessage());
-	    } finally {
-	        OdUtils.deleteDir(temp);
-	    	if (progressMonitor != null) {
-	    		progressMonitor.finishTask();
-	    	}
-	    }
-		
-		return ds;
-	}
+
+    protected void extractArchive(final File temp, final List<File> candidates) throws IOException, FileNotFoundException {
+        while ((entry = zis.getNextEntry()) != null) {
+            File file = new File(temp + File.separator + entry.getName());
+            File parent = file.getParentFile();
+            if (parent != null && !parent.exists()) {
+                parent.mkdirs();
+            }
+            if (file.exists() && !file.delete()) {
+                throw new IOException("Could not delete temp file/dir: " + file.getAbsolutePath());
+            }
+            if (!entry.isDirectory()) {
+                if (!file.createNewFile()) { 
+                    throw new IOException("Could not create temp file: " + file.getAbsolutePath());
+                }
+                // Write temp file
+                FileOutputStream fos = new FileOutputStream(file);
+                byte[] buffer = new byte[8192];
+                int count = 0;
+                while ((count = zis.read(buffer, 0, buffer.length)) > 0) {
+                    fos.write(buffer, 0, count);
+                }
+                fos.close();
+                // Allow handler to perform specific treatments (for example, fix invalid .prj files)
+                if (archiveHandler != null) {
+                    archiveHandler.notifyTempFileWritten(file);
+                }
+                // Set last modification date
+                long time = entry.getTime();
+                if (time > -1) {
+                    file.setLastModified(time);
+                }
+                lookForCandidate(entry.getName(), candidates, file);
+            } else if (!file.mkdir()) {
+                throw new IOException("Could not create temp dir: " + file.getAbsolutePath());
+            }
+        }
+    }
+
+    @Override protected String getTaskMessage() {
+        return tr("Reading Zip file...");
+    }
 }
