Index: src/org/openstreetmap/josm/actions/DiskAccessAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/DiskAccessAction.java	(revision 1713)
+++ src/org/openstreetmap/josm/actions/DiskAccessAction.java	(working copy)
@@ -5,7 +5,6 @@
 
 import java.io.File;
 import javax.swing.JFileChooser;
-import javax.swing.filechooser.FileFilter;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -56,50 +55,4 @@
         return fc;
     }
 
-    public static File createAndOpenSaveFileChooser(String title,
-    String extension)
-    {
-        String curDir = Main.pref.get("lastDirectory");
-        if (curDir.equals(""))
-            curDir = ".";
-        JFileChooser fc = new JFileChooser(new File(curDir));
-        if (title != null)
-            fc.setDialogTitle(title);
-
-        fc.setMultiSelectionEnabled(false);
-        for (FileImporter imExporter: ExtensionFileFilter.importers) {
-            fc.addChoosableFileFilter(imExporter.filter);
-        }
-
-        fc.setAcceptAllFileFilterUsed(true);
-
-        int answer = fc.showSaveDialog(Main.parent);
-        if (answer != JFileChooser.APPROVE_OPTION)
-            return null;
-
-        if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir))
-            Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
-
-        File file = fc.getSelectedFile();
-        if(extension != null)
-        {
-            String fn = file.getPath();
-            if(fn.indexOf('.') == -1)
-            {
-                FileFilter ff = fc.getFileFilter();
-                if (ff instanceof ExtensionFileFilter)
-                    fn += "." + ((ExtensionFileFilter)ff).defaultExtension;
-                else
-                    fn += extension;
-                file = new File(fn);
-            }
-        }
-        if(file == null || (file.exists() && 1 != new ExtendedDialog(Main.parent,
-        tr("Overwrite"), tr("File exists. Overwrite?"),
-        new String[] {tr("Overwrite"), tr("Cancel")},
-        new String[] {"save_as.png", "cancel.png"}).getValue()))
-            return null;
-        return file;
-    }
-
 }
Index: src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
===================================================================
--- src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 1713)
+++ src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(working copy)
@@ -1,6 +1,7 @@
 // License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.actions;
 
+import static org.openstreetmap.josm.tools.I18n.tr;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -8,12 +9,18 @@
 import javax.swing.filechooser.FileFilter;
 
 import org.openstreetmap.josm.io.FileImporter;
+import org.openstreetmap.josm.io.GpxExporter;
 import org.openstreetmap.josm.io.GpxImporter;
 import org.openstreetmap.josm.io.NMEAImporter;
+import org.openstreetmap.josm.io.OsmBzip2Exporter;
 import org.openstreetmap.josm.io.OsmBzip2Importer;
+import org.openstreetmap.josm.io.OsmExporter;
+import org.openstreetmap.josm.io.OsmGzipExporter;
 import org.openstreetmap.josm.io.OsmGzipImporter;
 import org.openstreetmap.josm.io.OsmImporter;
 
+import org.openstreetmap.josm.io.FileExporter;
+
 /**
  * A file filter that filters after the extension. Also includes a list of file
  * filters used in JOSM.
@@ -28,6 +35,10 @@
     public static ArrayList<FileImporter> importers = new ArrayList<FileImporter>(Arrays.asList(new OsmImporter(),
             new OsmGzipImporter(), new OsmBzip2Importer(), new GpxImporter(), new NMEAImporter()));
 
+    // list of supported export formats
+    public static ArrayList<FileExporter> exporters = new ArrayList<FileExporter>(Arrays.asList(new GpxExporter(),
+            new OsmExporter(), new OsmGzipExporter(), new OsmBzip2Exporter()));
+
     /**
      * Construct an extension file filter by giving the extension to check after.
      *
Index: src/org/openstreetmap/josm/actions/GpxExportAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/GpxExportAction.java	(revision 1713)
+++ src/org/openstreetmap/josm/actions/GpxExportAction.java	(working copy)
@@ -3,263 +3,58 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
-import java.util.Calendar;
 
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-import javax.swing.JFileChooser;
-import javax.swing.JLabel;
-import javax.swing.JList;
 import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTextArea;
-import javax.swing.JTextField;
-import javax.swing.ListSelectionModel;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.io.GpxWriter;
-import org.openstreetmap.josm.tools.GBC;
+import org.openstreetmap.josm.io.FileExporter;
+import org.openstreetmap.josm.io.GpxExporter;
 import org.openstreetmap.josm.tools.Shortcut;
 
 /**
  * Exports data to gpx.
  */
-public class GpxExportAction extends DiskAccessAction {
-
-    private final static String warningGpl = "<html><font color='red' size='-2'>"+tr("Note: GPL is not compatible with the OSM license. Do not upload GPL licensed tracks.")+"</html>";
+public class GpxExportAction extends SaveActionBase {
 
-    private final Layer layer;
+    public final static String warningGpl = "<html><font color='red' size='-2'>"+tr("Note: GPL is not compatible with the OSM license. Do not upload GPL licensed tracks.")+"</html>";
 
     public GpxExportAction(Layer layer) {
         super(tr("Export to GPX..."), "exportgpx", tr("Export the data to GPX file."),
-        Shortcut.registerShortcut("file:exportgpx", tr("Export to GPX..."), KeyEvent.VK_E, Shortcut.GROUP_MENU));
-        this.layer = layer;
+                Shortcut.registerShortcut("file:exportgpx", tr("Export to GPX..."), KeyEvent.VK_E, Shortcut.GROUP_MENU),
+                layer);
     }
 
+    @Override
     public void actionPerformed(ActionEvent e) {
         if (layer == null && Main.map == null) {
             JOptionPane.showMessageDialog(Main.parent, tr("Nothing to export. Get some data first."));
             return;
         }
 
-        JFileChooser fc = createAndOpenFileChooser(false, false, null);
-        if (fc == null)
-            return;
-        File file = fc.getSelectedFile();
+        File file = createAndOpenSaveFileChooser(tr("Export GPX file"),".gpx");
         if (file == null)
             return;
 
-        exportGpx(file, this.layer == null ? Main.main.editLayer() : this.layer);
-    }
-
-    public static void exportGpx(File file, Layer layer) {
-        String fn = file.getPath();
-        if (fn.indexOf('.') == -1) {
-            fn += ".gpx";
-            file = new File(fn);
-        }
-
-        // open the dialog asking for options
-        JPanel p = new JPanel(new GridBagLayout());
-
-        p.add(new JLabel(tr("gps track description")), GBC.eol());
-        JTextArea desc = new JTextArea(3,40);
-        desc.setWrapStyleWord(true);
-        desc.setLineWrap(true);
-        p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH));
-
-        JCheckBox author = new JCheckBox(tr("Add author information"), Main.pref.getBoolean("lastAddAuthor", true));
-        author.setSelected(true);
-        p.add(author, GBC.eol());
-        JLabel nameLabel = new JLabel(tr("Real name"));
-        p.add(nameLabel, GBC.std().insets(10,0,5,0));
-        JTextField authorName = new JTextField(Main.pref.get("lastAuthorName"));
-        p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL));
-        JLabel emailLabel = new JLabel(tr("E-Mail"));
-        p.add(emailLabel, GBC.std().insets(10,0,5,0));
-        JTextField email = new JTextField(Main.pref.get("osm-server.username"));
-        p.add(email, GBC.eol().fill(GBC.HORIZONTAL));
-        JLabel copyrightLabel = new JLabel(tr("Copyright (URL)"));
-        p.add(copyrightLabel, GBC.std().insets(10,0,5,0));
-        JTextField copyright = new JTextField();
-        p.add(copyright, GBC.std().fill(GBC.HORIZONTAL));
-        JButton predefined = new JButton(tr("Predefined"));
-        p.add(predefined, GBC.eol().insets(5,0,0,0));
-        JLabel copyrightYearLabel = new JLabel(tr("Copyright year"));
-        p.add(copyrightYearLabel, GBC.std().insets(10,0,5,5));
-        JTextField copyrightYear = new JTextField("");
-        p.add(copyrightYear, GBC.eol().fill(GBC.HORIZONTAL));
-        JLabel warning = new JLabel("<html><font size='-2'>&nbsp;</html");
-        p.add(warning, GBC.eol().fill(GBC.HORIZONTAL).insets(15,0,0,0));
-        addDependencies(author, authorName, email, copyright, predefined, copyrightYear, nameLabel, emailLabel, copyrightLabel, copyrightYearLabel, warning);
-
-        // if the user name is not the email address, but the osm user name
-        // move it from the email textfield to the author textfield
-        if(!email.getText().contains("@")) {
-            authorName.setText(email.getText());
-            email.setText("");
-        }
-
-        p.add(new JLabel(tr("Keywords")), GBC.eol());
-        JTextField keywords = new JTextField();
-        p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
-
-        int answer = new ExtendedDialog(Main.parent,
-                        tr("Export options"),
-                        p,
-                        new String[] {tr("Export and Save"), tr("Cancel")},
-                        new String[] {"exportgpx.png", "cancel.png"}).getValue();
-        if (answer != 1)
-            return;
-
-        Main.pref.put("lastAddAuthor", author.isSelected());
-        if (authorName.getText().length() != 0)
-            Main.pref.put("lastAuthorName", authorName.getText());
-        if (copyright.getText().length() != 0)
-            Main.pref.put("lastCopyright", copyright.getText());
-
-        GpxData gpxData;
-        if (layer instanceof OsmDataLayer)
-            gpxData = ((OsmDataLayer)layer).toGpxData();
-        else if (layer instanceof GpxLayer)
-            gpxData = ((GpxLayer)layer).data;
-        else
-            gpxData = OsmDataLayer.toGpxData(Main.ds, file);
-
-        // add author and copyright details to the gpx data
-        if(author.isSelected()) {
-            if(authorName.getText().length() > 0) {
-                gpxData.attr.put(GpxData.META_AUTHOR_NAME, authorName.getText());
-                gpxData.attr.put(GpxData.META_COPYRIGHT_AUTHOR, authorName.getText());
-            }
-            if(email.getText().length() > 0) gpxData.attr.put(GpxData.META_AUTHOR_EMAIL, email.getText());
-            if(copyright.getText().length() > 0) gpxData.attr.put(GpxData.META_COPYRIGHT_LICENSE, copyright.getText());
-            if(copyrightYear.getText().length() > 0) gpxData.attr.put(GpxData.META_COPYRIGHT_YEAR, copyrightYear.getText());
-        }
-
-        // add the description to the gpx data
-        if(desc.getText().length() > 0) gpxData.attr.put(GpxData.META_DESC, desc.getText());
-
-        // add keywords to the gpx data
-        if(keywords.getText().length() > 0) gpxData.attr.put(GpxData.META_KEYWORDS, keywords.getText());
-
-        try {
-            FileOutputStream fo = new FileOutputStream(file);
-            new GpxWriter(fo).write(gpxData);
-            fo.flush();
-            fo.close();
-        } catch (IOException x) {
-            x.printStackTrace();
-            JOptionPane.showMessageDialog(Main.parent, tr("Error while exporting {0}:\n{1}", fn,x.getMessage()), tr("Error"), JOptionPane.ERROR_MESSAGE);
-        }
-    }
-
-    /**
-     * Add all those listeners to handle the enable state of the fields.
-     * @param copyrightYearLabel
-     * @param copyrightLabel
-     * @param emailLabel
-     * @param nameLabel
-     * @param warning
-     */
-    private static void addDependencies(
-            final JCheckBox author,
-            final JTextField authorName,
-            final JTextField email,
-            final JTextField copyright,
-            final JButton predefined,
-            final JTextField copyrightYear,
-            final JLabel nameLabel,
-            final JLabel emailLabel,
-            final JLabel copyrightLabel,
-            final JLabel copyrightYearLabel,
-            final JLabel warning) {
-
-        ActionListener authorActionListener = new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                boolean b = author.isSelected();
-                authorName.setEnabled(b);
-                email.setEnabled(b);
-                nameLabel.setEnabled(b);
-                emailLabel.setEnabled(b);
-                authorName.setText(b ? Main.pref.get("lastAuthorName") : "");
-                email.setText(b ? Main.pref.get("osm-server.username") : "");
-
-                boolean authorSet = authorName.getText().length() != 0;
-                enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b && authorSet);
-            }
-        };
-        author.addActionListener(authorActionListener);
-
-        KeyAdapter authorNameListener = new KeyAdapter(){
-                    @Override public void keyReleased(KeyEvent e) {
-                        boolean b = authorName.getText().length()!=0 && author.isSelected();
-                        enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b);
-                    }
-                };
-        authorName.addKeyListener(authorNameListener);
-
-        predefined.addActionListener(new ActionListener(){
-            public void actionPerformed(ActionEvent e) {
-                JList l = new JList(new String[]{"Creative Commons By-SA", "public domain", "GNU Lesser Public License (LGPL)", "BSD License (MIT/X11)"});
-                l.setVisibleRowCount(4);
-                l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-                int answer = JOptionPane.showConfirmDialog(Main.parent, new JScrollPane(l),tr("Choose a predefined license"), JOptionPane.OK_CANCEL_OPTION);
-                if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1)
-                    return;
-                final String[] urls = {
-                        "http://creativecommons.org/licenses/by-sa/2.5",
-                        "public domain",
-                        "http://www.gnu.org/copyleft/lesser.html",
-                        "http://www.opensource.org/licenses/bsd-license.php"};
-                String license = "";
-                for (int i : l.getSelectedIndices()) {
-                    if (i == 1) {
-                        license = "public domain";
-                        break;
-                    }
-                    license += license.length()==0 ? urls[i] : ", "+urls[i];
+        for (FileExporter exporter : ExtensionFileFilter.exporters) {
+            if(exporter instanceof GpxExporter) {
+                try {
+                    exporter.exportData(file, this.layer == null ? Main.main.editLayer() : this.layer);
+                } catch (IOException e1) {
+                    e1.printStackTrace();
                 }
-                copyright.setText(license);
-                copyright.setCaretPosition(0);
             }
-        });
-
-        authorActionListener.actionPerformed(null);
-        authorNameListener.keyReleased(null);
+        }
     }
 
-    private static void enableCopyright(final JTextField copyright, final JButton predefined, final JTextField copyrightYear, final JLabel copyrightLabel, final JLabel copyrightYearLabel, final JLabel warning, boolean enable) {
-        copyright.setEnabled(enable);
-        predefined.setEnabled(enable);
-        copyrightYear.setEnabled(enable);
-        copyrightLabel.setEnabled(enable);
-        copyrightYearLabel.setEnabled(enable);
-        warning.setText(enable ? warningGpl : "<html><font size='-2'>&nbsp;</html");
-
-        if (enable && copyrightYear.getText().length()==0) {
-            copyrightYear.setText(enable ? Integer.toString(Calendar.getInstance().get(Calendar.YEAR)) : "");
-        } else if (!enable)
-            copyrightYear.setText("");
-
-        if (enable && copyright.getText().length()==0) {
-            copyright.setText(enable ? Main.pref.get("lastCopyright", "http://creativecommons.org/licenses/by-sa/2.5") : "");
-            copyright.setCaretPosition(0);
-        } else if (!enable)
-            copyright.setText("");
+    //Function not used here
+    @Override public File getFile(Layer layer) {
+        return null;
     }
 }
Index: src/org/openstreetmap/josm/actions/SaveActionBase.java
===================================================================
--- src/org/openstreetmap/josm/actions/SaveActionBase.java	(revision 1713)
+++ src/org/openstreetmap/josm/actions/SaveActionBase.java	(working copy)
@@ -9,32 +9,24 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Writer;
-import java.util.zip.GZIPOutputStream;
 
+import javax.swing.JFileChooser;
 import javax.swing.JOptionPane;
+import javax.swing.filechooser.FileFilter;
 
-import org.apache.tools.bzip2.CBZip2OutputStream;
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.gui.ExtendedDialog;
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.io.GpxImporter;
-import org.openstreetmap.josm.io.GpxWriter;
-import org.openstreetmap.josm.io.OsmBzip2Importer;
-import org.openstreetmap.josm.io.OsmGzipImporter;
-import org.openstreetmap.josm.io.OsmImporter;
-import org.openstreetmap.josm.io.OsmWriter;
+import org.openstreetmap.josm.io.FileExporter;
+import org.openstreetmap.josm.io.FileImporter;
 import org.openstreetmap.josm.tools.Shortcut;
 
 public abstract class SaveActionBase extends DiskAccessAction {
 
-    private Layer layer;
+    protected Layer layer;
 
     public SaveActionBase(String name, String iconName, String tooltip, Shortcut shortcut, Layer layer) {
         super(name, iconName, tooltip, shortcut);
@@ -48,10 +40,12 @@
     public Boolean doSave() {
         Layer layer = this.layer;
         if (layer == null && Main.map != null && (Main.map.mapView.getActiveLayer() instanceof OsmDataLayer
-                || Main.map.mapView.getActiveLayer() instanceof GpxLayer))
+                || Main.map.mapView.getActiveLayer() instanceof GpxLayer)) {
             layer = Main.map.mapView.getActiveLayer();
-        if (layer == null)
+        }
+        if (layer == null) {
             layer = Main.main.editLayer();
+        }
 
         if (!checkSaveConditions(layer))
             return false;
@@ -61,11 +55,21 @@
         if (file == null)
             return false;
 
-        save(file, layer);
+        try {
+            for (FileExporter exporter : ExtensionFileFilter.exporters) {
+                if(exporter.acceptFile(file)) {
+                    exporter.exportData(file, layer);
+                }
+            }
+
+            layer.name = file.getName();
+            layer.setAssociatedFile(file);
+            Main.parent.repaint();
 
-        layer.name = file.getName();
-        layer.setAssociatedFile(file);
-        Main.parent.repaint();
+        } catch (IOException e) {
+            e.printStackTrace();
+            return false;
+        }
         return true;
     }
 
@@ -86,18 +90,16 @@
             return false;
         }
 
-        if (layer instanceof OsmDataLayer && isDataSetEmpty((OsmDataLayer)layer) && 1 != new ExtendedDialog(Main.parent, tr("Empty document"), tr("The document contains no data."), new String[] {tr("Save anyway"), tr("Cancel")}, new String[] {"save.png", "cancel.png"}).getValue()) {
+        if (layer instanceof OsmDataLayer && isDataSetEmpty((OsmDataLayer)layer) && 1 != new ExtendedDialog(Main.parent, tr("Empty document"), tr("The document contains no data."), new String[] {tr("Save anyway"), tr("Cancel")}, new String[] {"save.png", "cancel.png"}).getValue())
             return false;
-        }
-        if (layer instanceof GpxLayer && ((GpxLayer)layer).data == null) {
+        if (layer instanceof GpxLayer && ((GpxLayer)layer).data == null)
             return false;
-        }
         if (!Main.map.conflictDialog.conflicts.isEmpty()) {
             int answer = new ExtendedDialog(Main.parent,
-                tr("Conflicts"),
-                tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"),
-                new String[] {tr("Reject Conflicts and Save"), tr("Cancel")},
-                new String[] {"save.png", "cancel.png"}).getValue();
+                    tr("Conflicts"),
+                    tr("There are unresolved conflicts. Conflicts will not be saved and handled as if you rejected all. Continue?"),
+                    new String[] {tr("Reject Conflicts and Save"), tr("Cancel")},
+                    new String[] {"save.png", "cancel.png"}).getValue();
 
             if (answer != 1) return false;
         }
@@ -106,13 +108,13 @@
 
     public static File openFileDialog(Layer layer) {
         if (layer instanceof OsmDataLayer)
-            return createAndOpenSaveFileChooser(tr("Save OSM file"), ".osm");
+            return SaveActionBase.createAndOpenSaveFileChooser(tr("Save OSM file"), ".osm");
         else if (layer instanceof GpxLayer)
-            return createAndOpenSaveFileChooser(tr("Save GPX file"), ".gpx");
-        return createAndOpenSaveFileChooser(tr("Save Layer"), ".lay");
+            return SaveActionBase.createAndOpenSaveFileChooser(tr("Save GPX file"), ".gpx");
+        return SaveActionBase.createAndOpenSaveFileChooser(tr("Save Layer"), ".lay");
     }
 
-    private static void copy(File src, File dst) throws IOException {
+    public static void copy(File src, File dst) throws IOException {
         FileInputStream srcStream;
         FileOutputStream dstStream;
         try {
@@ -131,119 +133,6 @@
         dstStream.close();
     }
 
-    public static void save(File file, Layer layer) {
-        if (layer instanceof GpxLayer) {
-            save(file, (GpxLayer)layer);
-            ((GpxLayer)layer).data.storageFile = file;
-        } else if (layer instanceof OsmDataLayer) {
-            save(file, (OsmDataLayer)layer);
-        }
-    }
-
-    public static void save(File file, OsmDataLayer layer) {
-        File tmpFile = null;
-        try {
-            GpxImporter gpxImExporter = new GpxImporter();
-            OsmImporter osmImExporter = new OsmImporter();
-            OsmGzipImporter osmGzipImporter = new OsmGzipImporter();
-            OsmBzip2Importer osmBzip2Importer = new OsmBzip2Importer();
-            if (gpxImExporter.acceptFile(file))
-                GpxExportAction.exportGpx(file, layer);
-            else if (osmImExporter.acceptFile(file)
-                    || osmGzipImporter.acceptFile(file)
-                    || osmBzip2Importer.acceptFile(file))
-            {
-                // use a tmp file because if something errors out in the
-                // process of writing the file, we might just end up with
-                // a truncated file.  That can destroy lots of work.
-                if (file.exists()) {
-                    tmpFile = new File(file.getPath() + "~");
-                    copy(file, tmpFile);
-                }
-
-                // create outputstream and wrap it with gzip or bzip, if necessary
-                OutputStream out = new FileOutputStream(file);
-                if(osmGzipImporter.acceptFile(file)) {
-                    out = new GZIPOutputStream(out);
-                } else if(osmBzip2Importer.acceptFile(file)) {
-                    out.write('B');
-                    out.write('Z');
-                    out = new CBZip2OutputStream(out);
-                }
-                Writer writer = new OutputStreamWriter(out, "UTF-8");
-
-                OsmWriter w = new OsmWriter(new PrintWriter(writer), false, layer.data.version);
-                w.header();
-                w.writeDataSources(layer.data);
-                w.writeContent(layer.data);
-                w.footer();
-                w.close();
-                // FIXME - how to close?
-                if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null))
-                    tmpFile.delete();
-            } else {
-                JOptionPane.showMessageDialog(Main.parent, tr("Unknown file extension."));
-                return;
-            }
-            layer.cleanData(null, false);
-        } catch (IOException e) {
-            e.printStackTrace();
-            JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage());
-
-            try {
-                // if the file save failed, then the tempfile will not
-                // be deleted.  So, restore the backup if we made one.
-                if (tmpFile != null && tmpFile.exists()) {
-                    copy(tmpFile, file);
-                }
-            } catch (IOException e2) {
-                e2.printStackTrace();
-                JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e2.getMessage());
-            }
-        }
-    }
-
-    public static void save(File file, GpxLayer layer) {
-        File tmpFile = null;
-        try {
-            GpxImporter gpxImExporter = new GpxImporter();
-            if (gpxImExporter.acceptFile(file)) {
-
-                // use a tmp file because if something errors out in the
-                // process of writing the file, we might just end up with
-                // a truncated file.  That can destroy lots of work.
-                if (file.exists()) {
-                    tmpFile = new File(file.getPath() + "~");
-                    copy(file, tmpFile);
-                }
-                FileOutputStream fo = new FileOutputStream(file);
-                new GpxWriter(fo).write(layer.data);
-                fo.flush();
-                fo.close();
-
-                if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) {
-                    tmpFile.delete();
-                }
-            } else {
-                JOptionPane.showMessageDialog(Main.parent, tr("Unknown file extension."));
-                return;
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-            JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage());
-        }
-        try {
-            // if the file save failed, then the tempfile will not
-            // be deleted.  So, restore the backup if we made one.
-            if (tmpFile != null && tmpFile.exists()) {
-                copy(tmpFile, file);
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-            JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e.getMessage());
-        }
-    }
-
     /**
      * Check the data set if it would be empty on save. It is empty, if it contains
      * no objects (after all objects that are created and deleted without being
@@ -257,4 +146,54 @@
                 return false;
         return true;
     }
+
+    public static File createAndOpenSaveFileChooser(String title,
+            String extension)
+    {
+        String curDir = Main.pref.get("lastDirectory");
+        if (curDir.equals("")) {
+            curDir = ".";
+        }
+        JFileChooser fc = new JFileChooser(new File(curDir));
+        if (title != null) {
+            fc.setDialogTitle(title);
+        }
+
+        fc.setMultiSelectionEnabled(false);
+        for (FileExporter exporter: ExtensionFileFilter.exporters) {
+            fc.addChoosableFileFilter(exporter.filter);
+        }
+
+        fc.setAcceptAllFileFilterUsed(true);
+
+        int answer = fc.showSaveDialog(Main.parent);
+        if (answer != JFileChooser.APPROVE_OPTION)
+            return null;
+
+        if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
+            Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
+        }
+
+        File file = fc.getSelectedFile();
+        if(extension != null)
+        {
+            String fn = file.getPath();
+            if(fn.indexOf('.') == -1)
+            {
+                FileFilter ff = fc.getFileFilter();
+                if (ff instanceof ExtensionFileFilter) {
+                    fn += "." + ((ExtensionFileFilter)ff).defaultExtension;
+                } else {
+                    fn += extension;
+                }
+                file = new File(fn);
+            }
+        }
+        if(file == null || (file.exists() && 1 != new ExtendedDialog(Main.parent,
+                tr("Overwrite"), tr("File exists. Overwrite?"),
+                new String[] {tr("Overwrite"), tr("Cancel")},
+                new String[] {"save_as.png", "cancel.png"}).getValue()))
+            return null;
+        return file;
+    }
 }
Index: src/org/openstreetmap/josm/io/FileExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/FileExporter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/FileExporter.java	(revision 0)
@@ -0,0 +1,26 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.gui.layer.Layer;
+
+public abstract class FileExporter {
+    public ExtensionFileFilter filter;
+
+    public FileExporter(ExtensionFileFilter filter) {
+        this.filter=filter;
+    }
+
+    public boolean acceptFile(File pathname) {
+        return filter.acceptName(pathname.getName());
+    }
+
+    public void exportData(File file,Layer layer) throws IOException {
+        throw new IOException(tr("Could not export \"{0}\"", file.getName()));
+    }
+}
Index: src/org/openstreetmap/josm/io/GpxExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxExporter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/GpxExporter.java	(revision 0)
@@ -0,0 +1,256 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Calendar;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.actions.GpxExportAction;
+import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.tools.GBC;
+
+public class GpxExporter extends FileExporter{
+
+    public GpxExporter() {
+        super(new ExtensionFileFilter("gpx,gpx.gz", "gpx", tr("GPX Files") + " (*.gpx *.gpx.gz)"));
+    }
+
+
+    private static void enableCopyright(final JTextField copyright, final JButton predefined, final JTextField copyrightYear, final JLabel copyrightLabel, final JLabel copyrightYearLabel, final JLabel warning, boolean enable) {
+        copyright.setEnabled(enable);
+        predefined.setEnabled(enable);
+        copyrightYear.setEnabled(enable);
+        copyrightLabel.setEnabled(enable);
+        copyrightYearLabel.setEnabled(enable);
+        warning.setText(enable ? GpxExportAction.warningGpl : "<html><font size='-2'>&nbsp;</html");
+
+        if (enable && copyrightYear.getText().length()==0) {
+            copyrightYear.setText(enable ? Integer.toString(Calendar.getInstance().get(Calendar.YEAR)) : "");
+        } else if (!enable) {
+            copyrightYear.setText("");
+        }
+
+        if (enable && copyright.getText().length()==0) {
+            copyright.setText(enable ? Main.pref.get("lastCopyright", "http://creativecommons.org/licenses/by-sa/2.5") : "");
+            copyright.setCaretPosition(0);
+        } else if (!enable) {
+            copyright.setText("");
+        }
+    }
+
+    /**
+     * Add all those listeners to handle the enable state of the fields.
+     * @param copyrightYearLabel
+     * @param copyrightLabel
+     * @param emailLabel
+     * @param nameLabel
+     * @param warning
+     */
+    private static void addDependencies(
+            final JCheckBox author,
+            final JTextField authorName,
+            final JTextField email,
+            final JTextField copyright,
+            final JButton predefined,
+            final JTextField copyrightYear,
+            final JLabel nameLabel,
+            final JLabel emailLabel,
+            final JLabel copyrightLabel,
+            final JLabel copyrightYearLabel,
+            final JLabel warning) {
+
+        ActionListener authorActionListener = new ActionListener(){
+            public void actionPerformed(ActionEvent e) {
+                boolean b = author.isSelected();
+                authorName.setEnabled(b);
+                email.setEnabled(b);
+                nameLabel.setEnabled(b);
+                emailLabel.setEnabled(b);
+                authorName.setText(b ? Main.pref.get("lastAuthorName") : "");
+                email.setText(b ? Main.pref.get("osm-server.username") : "");
+
+                boolean authorSet = authorName.getText().length() != 0;
+                enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b && authorSet);
+            }
+        };
+        author.addActionListener(authorActionListener);
+
+        KeyAdapter authorNameListener = new KeyAdapter(){
+            @Override public void keyReleased(KeyEvent e) {
+                boolean b = authorName.getText().length()!=0 && author.isSelected();
+                enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b);
+            }
+        };
+        authorName.addKeyListener(authorNameListener);
+
+        predefined.addActionListener(new ActionListener(){
+            public void actionPerformed(ActionEvent e) {
+                JList l = new JList(new String[]{"Creative Commons By-SA", "public domain", "GNU Lesser Public License (LGPL)", "BSD License (MIT/X11)"});
+                l.setVisibleRowCount(4);
+                l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
+                int answer = JOptionPane.showConfirmDialog(Main.parent, new JScrollPane(l),tr("Choose a predefined license"), JOptionPane.OK_CANCEL_OPTION);
+                if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1)
+                    return;
+                final String[] urls = {
+                        "http://creativecommons.org/licenses/by-sa/2.5",
+                        "public domain",
+                        "http://www.gnu.org/copyleft/lesser.html",
+                "http://www.opensource.org/licenses/bsd-license.php"};
+                String license = "";
+                for (int i : l.getSelectedIndices()) {
+                    if (i == 1) {
+                        license = "public domain";
+                        break;
+                    }
+                    license += license.length()==0 ? urls[i] : ", "+urls[i];
+                }
+                copyright.setText(license);
+                copyright.setCaretPosition(0);
+            }
+        });
+
+        authorActionListener.actionPerformed(null);
+        authorNameListener.keyReleased(null);
+    }
+
+    @Override
+    public void exportData(File file,Layer layer) throws IOException {
+        String fn = file.getPath();
+        if (fn.indexOf('.') == -1) {
+            fn += ".gpx";
+            file = new File(fn);
+        }
+
+        // open the dialog asking for options
+        JPanel p = new JPanel(new GridBagLayout());
+
+        p.add(new JLabel(tr("gps track description")), GBC.eol());
+        JTextArea desc = new JTextArea(3,40);
+        desc.setWrapStyleWord(true);
+        desc.setLineWrap(true);
+        p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH));
+
+        JCheckBox author = new JCheckBox(tr("Add author information"), Main.pref.getBoolean("lastAddAuthor", true));
+        author.setSelected(true);
+        p.add(author, GBC.eol());
+        JLabel nameLabel = new JLabel(tr("Real name"));
+        p.add(nameLabel, GBC.std().insets(10,0,5,0));
+        JTextField authorName = new JTextField(Main.pref.get("lastAuthorName"));
+        p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL));
+        JLabel emailLabel = new JLabel(tr("E-Mail"));
+        p.add(emailLabel, GBC.std().insets(10,0,5,0));
+        JTextField email = new JTextField(Main.pref.get("osm-server.username"));
+        p.add(email, GBC.eol().fill(GBC.HORIZONTAL));
+        JLabel copyrightLabel = new JLabel(tr("Copyright (URL)"));
+        p.add(copyrightLabel, GBC.std().insets(10,0,5,0));
+        JTextField copyright = new JTextField();
+        p.add(copyright, GBC.std().fill(GBC.HORIZONTAL));
+        JButton predefined = new JButton(tr("Predefined"));
+        p.add(predefined, GBC.eol().insets(5,0,0,0));
+        JLabel copyrightYearLabel = new JLabel(tr("Copyright year"));
+        p.add(copyrightYearLabel, GBC.std().insets(10,0,5,5));
+        JTextField copyrightYear = new JTextField("");
+        p.add(copyrightYear, GBC.eol().fill(GBC.HORIZONTAL));
+        JLabel warning = new JLabel("<html><font size='-2'>&nbsp;</html");
+        p.add(warning, GBC.eol().fill(GBC.HORIZONTAL).insets(15,0,0,0));
+        GpxExporter.addDependencies(author, authorName, email, copyright, predefined, copyrightYear, nameLabel, emailLabel, copyrightLabel, copyrightYearLabel, warning);
+
+        // if the user name is not the email address, but the osm user name
+        // move it from the email textfield to the author textfield
+        if(!email.getText().contains("@")) {
+            authorName.setText(email.getText());
+            email.setText("");
+        }
+
+        p.add(new JLabel(tr("Keywords")), GBC.eol());
+        JTextField keywords = new JTextField();
+        p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
+
+        int answer = new ExtendedDialog(Main.parent,
+                tr("Export options"),
+                p,
+                new String[] {tr("Export and Save"), tr("Cancel")},
+                new String[] {"exportgpx.png", "cancel.png"}).getValue();
+        if (answer != 1)
+            return;
+
+        Main.pref.put("lastAddAuthor", author.isSelected());
+        if (authorName.getText().length() != 0) {
+            Main.pref.put("lastAuthorName", authorName.getText());
+        }
+        if (copyright.getText().length() != 0) {
+            Main.pref.put("lastCopyright", copyright.getText());
+        }
+
+        GpxData gpxData;
+        if (layer instanceof OsmDataLayer) {
+            gpxData = ((OsmDataLayer)layer).toGpxData();
+        } else if (layer instanceof GpxLayer) {
+            gpxData = ((GpxLayer)layer).data;
+        } else {
+            gpxData = OsmDataLayer.toGpxData(Main.ds, file);
+        }
+
+        // add author and copyright details to the gpx data
+        if(author.isSelected()) {
+            if(authorName.getText().length() > 0) {
+                gpxData.attr.put(GpxData.META_AUTHOR_NAME, authorName.getText());
+                gpxData.attr.put(GpxData.META_COPYRIGHT_AUTHOR, authorName.getText());
+            }
+            if(email.getText().length() > 0) {
+                gpxData.attr.put(GpxData.META_AUTHOR_EMAIL, email.getText());
+            }
+            if(copyright.getText().length() > 0) {
+                gpxData.attr.put(GpxData.META_COPYRIGHT_LICENSE, copyright.getText());
+            }
+            if(copyrightYear.getText().length() > 0) {
+                gpxData.attr.put(GpxData.META_COPYRIGHT_YEAR, copyrightYear.getText());
+            }
+        }
+
+        // add the description to the gpx data
+        if(desc.getText().length() > 0) {
+            gpxData.attr.put(GpxData.META_DESC, desc.getText());
+        }
+
+        // add keywords to the gpx data
+        if(keywords.getText().length() > 0) {
+            gpxData.attr.put(GpxData.META_KEYWORDS, keywords.getText());
+        }
+
+        try {
+            FileOutputStream fo = new FileOutputStream(file);
+            new GpxWriter(fo).write(gpxData);
+            fo.flush();
+            fo.close();
+        } catch (IOException x) {
+            x.printStackTrace();
+            JOptionPane.showMessageDialog(Main.parent, tr("Error while exporting {0}:\n{1}", fn,x.getMessage()), tr("Error"), JOptionPane.ERROR_MESSAGE);
+        }
+    }
+}
Index: src/org/openstreetmap/josm/io/OsmBzip2Exporter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmBzip2Exporter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/OsmBzip2Exporter.java	(revision 0)
@@ -0,0 +1,30 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+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.OutputStream;
+
+import org.apache.tools.bzip2.CBZip2OutputStream;
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+
+public class OsmBzip2Exporter extends OsmExporter {
+
+    public OsmBzip2Exporter() {
+        super(new ExtensionFileFilter("osm.bz2, osm.bz", "osm.bz2", tr("OSM Server Files bzip2 compressed")
+                + " (*.osm.bz2 *.osm.bz)"));
+    }
+
+    @Override
+    protected OutputStream getOutputStream(File file) throws FileNotFoundException,IOException {
+        OutputStream out = new FileOutputStream(file);
+        out.write('B');
+        out.write('Z');
+        out = new CBZip2OutputStream(out);
+        return out;
+    }
+}
Index: src/org/openstreetmap/josm/io/OsmExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmExporter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/OsmExporter.java	(revision 0)
@@ -0,0 +1,129 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+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.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+import javax.swing.JOptionPane;
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.actions.SaveActionBase;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+
+public class OsmExporter extends FileExporter {
+
+    public OsmExporter() {
+        super(new ExtensionFileFilter("osm,xml", "osm", tr("OSM Server Files") + " (*.osm *.xml)"));
+    }
+
+    public OsmExporter(ExtensionFileFilter filter) {
+        super(filter);
+    }
+
+    @Override
+    public void exportData(File file, Layer layer) throws IOException {
+        if (layer instanceof GpxLayer) {
+            save(file, (GpxLayer)layer);
+            ((GpxLayer)layer).data.storageFile = file;
+        } else if (layer instanceof OsmDataLayer) {
+            save(file, (OsmDataLayer)layer);
+        }
+    }
+
+    private void save(File file, OsmDataLayer layer) {
+        File tmpFile = null;
+        try {
+            // use a tmp file because if something errors out in the
+            // process of writing the file, we might just end up with
+            // a truncated file.  That can destroy lots of work.
+            if (file.exists()) {
+                tmpFile = new File(file.getPath() + "~");
+                SaveActionBase.copy(file, tmpFile);
+            }
+
+            // create outputstream and wrap it with gzip or bzip, if necessary
+            OutputStream out = getOutputStream(file);
+            Writer writer = new OutputStreamWriter(out, "UTF-8");
+
+            OsmWriter w = new OsmWriter(new PrintWriter(writer), false, layer.data.version);
+            w.header();
+            w.writeDataSources(layer.data);
+            w.writeContent(layer.data);
+            w.footer();
+            w.close();
+            // FIXME - how to close?
+            if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) {
+                tmpFile.delete();
+            }
+            layer.cleanData(null, false);
+        } catch (IOException e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage());
+
+            try {
+                // if the file save failed, then the tempfile will not
+                // be deleted.  So, restore the backup if we made one.
+                if (tmpFile != null && tmpFile.exists()) {
+                    SaveActionBase.copy(tmpFile, file);
+                }
+            } catch (IOException e2) {
+                e2.printStackTrace();
+                JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e2.getMessage());
+            }
+        }
+    }
+
+    protected OutputStream getOutputStream(File file) throws FileNotFoundException,IOException {
+        return new FileOutputStream(file);
+    }
+
+    private void save(File file, GpxLayer layer) {
+        File tmpFile = null;
+        try {
+            GpxImporter gpxImExporter = new GpxImporter();
+            if (gpxImExporter.acceptFile(file)) {
+
+                // use a tmp file because if something errors out in the
+                // process of writing the file, we might just end up with
+                // a truncated file.  That can destroy lots of work.
+                if (file.exists()) {
+                    tmpFile = new File(file.getPath() + "~");
+                    SaveActionBase.copy(file, tmpFile);
+                }
+                FileOutputStream fo = (FileOutputStream) getOutputStream(file);
+                new GpxWriter(fo).write(layer.data);
+                fo.flush();
+                fo.close();
+
+                if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) {
+                    tmpFile.delete();
+                }
+            } else {
+                JOptionPane.showMessageDialog(Main.parent, tr("Unknown file extension."));
+                return;
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while saving.")+"\n"+e.getMessage());
+        }
+        try {
+            // if the file save failed, then the tempfile will not
+            // be deleted.  So, restore the backup if we made one.
+            if (tmpFile != null && tmpFile.exists()) {
+                SaveActionBase.copy(tmpFile, file);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(Main.parent, tr("An error occurred while restoring backup file.")+"\n"+e.getMessage());
+        }
+    }
+}
Index: src/org/openstreetmap/josm/io/OsmGzipExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmGzipExporter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/OsmGzipExporter.java	(revision 0)
@@ -0,0 +1,26 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+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.OutputStream;
+import java.util.zip.GZIPOutputStream;
+
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+
+public class OsmGzipExporter extends OsmExporter {
+
+    public OsmGzipExporter() {
+        super(new ExtensionFileFilter("osm.gz", "osm.gz", tr("OSM Server Files gzip compressed") + " (*.osm.gz)"));
+    }
+
+    @Override
+    protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException {
+        OutputStream out = new FileOutputStream(file);
+        return new GZIPOutputStream(out);
+    }
+}
