001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.File;
007import java.io.FileNotFoundException;
008import java.io.FileOutputStream;
009import java.io.IOException;
010import java.io.OutputStream;
011import java.io.OutputStreamWriter;
012import java.io.PrintWriter;
013import java.io.Writer;
014import java.text.MessageFormat;
015
016import javax.swing.JOptionPane;
017
018import org.openstreetmap.josm.Main;
019import org.openstreetmap.josm.actions.ExtensionFileFilter;
020import org.openstreetmap.josm.gui.layer.Layer;
021import org.openstreetmap.josm.gui.layer.OsmDataLayer;
022import org.openstreetmap.josm.tools.Utils;
023
024public class OsmExporter extends FileExporter {
025
026    public OsmExporter() {
027        super(OsmImporter.FILE_FILTER);
028    }
029
030    public OsmExporter(ExtensionFileFilter filter) {
031        super(filter);
032    }
033
034    @Override
035    public boolean acceptFile(File pathname, Layer layer) {
036        if (!(layer instanceof OsmDataLayer))
037            return false;
038        return super.acceptFile(pathname, layer);
039    }
040
041    @Override
042    public void exportData(File file, Layer layer) throws IOException {
043        exportData(file, layer, false);
044    }
045
046    public void exportData(File file, Layer layer, boolean noBackup) throws IOException {
047        if (layer instanceof OsmDataLayer) {
048            save(file, (OsmDataLayer) layer, noBackup);
049        } else
050            throw new IllegalArgumentException(MessageFormat.format("Expected instance of OsmDataLayer. Got ''{0}''.", layer
051                    .getClass().getName()));
052    }
053
054    protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException {
055        return new FileOutputStream(file);
056    }
057
058    private void save(File file, OsmDataLayer layer, boolean noBackup) {
059        File tmpFile = null;
060        try {
061            // use a tmp file because if something errors out in the
062            // process of writing the file, we might just end up with
063            // a truncated file.  That can destroy lots of work.
064            if (file.exists()) {
065                tmpFile = new File(file.getPath() + "~");
066                Utils.copyFile(file, tmpFile);
067            }
068
069            // create outputstream and wrap it with gzip or bzip, if necessary
070            OutputStream out = getOutputStream(file);
071            Writer writer = new OutputStreamWriter(out, "UTF-8");
072
073            OsmWriter w = OsmWriterFactory.createOsmWriter(new PrintWriter(writer), false, layer.data.getVersion());
074            layer.data.getReadLock().lock();
075            try {
076                w.writeLayer(layer);
077            } finally {
078                Utils.close(w);
079                layer.data.getReadLock().unlock();
080            }
081            // FIXME - how to close?
082            if (noBackup || !Main.pref.getBoolean("save.keepbackup", false)) {
083                if (tmpFile != null) {
084                    tmpFile.delete();
085                }
086            }
087            layer.onPostSaveToFile();
088        } catch (IOException e) {
089            e.printStackTrace();
090            JOptionPane.showMessageDialog(
091                    Main.parent,
092                    tr("<html>An error occurred while saving.<br>Error is:<br>{0}</html>", e.getMessage()),
093                    tr("Error"),
094                    JOptionPane.ERROR_MESSAGE
095            );
096
097            try {
098                // if the file save failed, then the tempfile will not
099                // be deleted.  So, restore the backup if we made one.
100                if (tmpFile != null && tmpFile.exists()) {
101                    Utils.copyFile(tmpFile, file);
102                }
103            } catch (IOException e2) {
104                e2.printStackTrace();
105                JOptionPane.showMessageDialog(
106                        Main.parent,
107                        tr("<html>An error occurred while restoring backup file.<br>Error is:<br>{0}</html>", e2.getMessage()),
108                        tr("Error"),
109                        JOptionPane.ERROR_MESSAGE
110                );
111            }
112        }
113    }
114}