001 // License: GPL. For details, see LICENSE file. 002 package org.openstreetmap.josm.io; 003 004 import static org.openstreetmap.josm.tools.I18n.tr; 005 006 import java.io.File; 007 import java.io.FileInputStream; 008 import java.io.FileNotFoundException; 009 import java.io.FileOutputStream; 010 import java.io.IOException; 011 import java.io.OutputStream; 012 import java.io.OutputStreamWriter; 013 import java.io.PrintWriter; 014 import java.io.Writer; 015 import java.text.MessageFormat; 016 017 import javax.swing.JOptionPane; 018 019 import org.openstreetmap.josm.Main; 020 import org.openstreetmap.josm.actions.ExtensionFileFilter; 021 import org.openstreetmap.josm.gui.layer.Layer; 022 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 023 024 public 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 copy(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 w.close(); 078 } finally { 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 copy(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 115 private void copy(File src, File dst) throws IOException { 116 FileInputStream srcStream; 117 FileOutputStream dstStream; 118 try { 119 srcStream = new FileInputStream(src); 120 dstStream = new FileOutputStream(dst); 121 } catch (FileNotFoundException e) { 122 JOptionPane.showMessageDialog(Main.parent, tr("Could not back up file. Exception is: {0}", e 123 .getMessage()), tr("Error"), JOptionPane.ERROR_MESSAGE); 124 return; 125 } 126 byte buf[] = new byte[1 << 16]; 127 int len; 128 while ((len = srcStream.read(buf)) != -1) { 129 dstStream.write(buf, 0, len); 130 } 131 srcStream.close(); 132 dstStream.close(); 133 } 134 135 }