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.IOException; 009import java.io.OutputStream; 010import java.io.OutputStreamWriter; 011import java.io.PrintWriter; 012import java.io.Writer; 013import java.nio.charset.StandardCharsets; 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 /** 027 * Constructs a new {@code OsmExporter}. 028 */ 029 public OsmExporter() { 030 super(OsmImporter.FILE_FILTER); 031 } 032 033 public OsmExporter(ExtensionFileFilter filter) { 034 super(filter); 035 } 036 037 @Override 038 public boolean acceptFile(File pathname, Layer layer) { 039 if (!(layer instanceof OsmDataLayer)) 040 return false; 041 return super.acceptFile(pathname, layer); 042 } 043 044 @Override 045 public void exportData(File file, Layer layer) throws IOException { 046 exportData(file, layer, false); 047 } 048 049 public void exportData(File file, Layer layer, boolean noBackup) throws IllegalArgumentException { 050 if (layer instanceof OsmDataLayer) { 051 save(file, (OsmDataLayer) layer, noBackup); 052 } else 053 throw new IllegalArgumentException(MessageFormat.format("Expected instance of OsmDataLayer. Got ''{0}''.", layer 054 .getClass().getName())); 055 } 056 057 protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException { 058 return Compression.getCompressedFileOutputStream(file); 059 } 060 061 private void save(File file, OsmDataLayer layer, boolean noBackup) { 062 File tmpFile = null; 063 try { 064 // use a tmp file because if something errors out in the 065 // process of writing the file, we might just end up with 066 // a truncated file. That can destroy lots of work. 067 if (file.exists()) { 068 tmpFile = new File(file.getPath() + "~"); 069 Utils.copyFile(file, tmpFile); 070 } 071 072 // create outputstream and wrap it with gzip or bzip, if necessary 073 try ( 074 OutputStream out = getOutputStream(file); 075 Writer writer = new OutputStreamWriter(out, StandardCharsets.UTF_8); 076 OsmWriter w = OsmWriterFactory.createOsmWriter(new PrintWriter(writer), false, layer.data.getVersion()); 077 ) { 078 layer.data.getReadLock().lock(); 079 try { 080 w.writeLayer(layer); 081 } finally { 082 layer.data.getReadLock().unlock(); 083 } 084 } 085 if (noBackup || !Main.pref.getBoolean("save.keepbackup", false)) { 086 if (tmpFile != null) { 087 tmpFile.delete(); 088 } 089 } 090 layer.onPostSaveToFile(); 091 } catch (IOException e) { 092 Main.error(e); 093 JOptionPane.showMessageDialog( 094 Main.parent, 095 tr("<html>An error occurred while saving.<br>Error is:<br>{0}</html>", e.getMessage()), 096 tr("Error"), 097 JOptionPane.ERROR_MESSAGE 098 ); 099 100 try { 101 // if the file save failed, then the tempfile will not 102 // be deleted. So, restore the backup if we made one. 103 if (tmpFile != null && tmpFile.exists()) { 104 Utils.copyFile(tmpFile, file); 105 } 106 } catch (IOException e2) { 107 Main.error(e2); 108 JOptionPane.showMessageDialog( 109 Main.parent, 110 tr("<html>An error occurred while restoring backup file.<br>Error is:<br>{0}</html>", e2.getMessage()), 111 tr("Error"), 112 JOptionPane.ERROR_MESSAGE 113 ); 114 } 115 } 116 } 117}