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 }