Ticket #1647: fileexport.txt

File fileexport.txt, 49.7 KB (added by dmuecke, 17 years ago)
Line 
1Index: src/org/openstreetmap/josm/actions/DiskAccessAction.java
2===================================================================
3--- src/org/openstreetmap/josm/actions/DiskAccessAction.java (revision 1946)
4+++ src/org/openstreetmap/josm/actions/DiskAccessAction.java (working copy)
5@@ -5,7 +5,6 @@
6
7 import java.io.File;
8 import javax.swing.JFileChooser;
9-import javax.swing.filechooser.FileFilter;
10 import org.openstreetmap.josm.Main;
11 import org.openstreetmap.josm.gui.ExtendedDialog;
12 import org.openstreetmap.josm.tools.Shortcut;
13@@ -58,51 +57,4 @@
14
15 return fc;
16 }
17-
18- public static File createAndOpenSaveFileChooser(String title, String extension) {
19- String curDir = Main.pref.get("lastDirectory");
20- if (curDir.equals("")) {
21- curDir = ".";
22- }
23- JFileChooser fc = new JFileChooser(new File(curDir));
24- if (title != null) {
25- fc.setDialogTitle(title);
26- }
27-
28- fc.setMultiSelectionEnabled(false);
29- for (FileImporter imExporter: ExtensionFileFilter.importers) {
30- fc.addChoosableFileFilter(imExporter.filter);
31- }
32-
33- fc.setAcceptAllFileFilterUsed(true);
34-
35- int answer = fc.showSaveDialog(Main.parent);
36- if (answer != JFileChooser.APPROVE_OPTION)
37- return null;
38-
39- if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
40- Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
41- }
42-
43- File file = fc.getSelectedFile();
44- if(extension != null){
45- String fn = file.getPath();
46- if(fn.indexOf('.') == -1)
47- {
48- FileFilter ff = fc.getFileFilter();
49- if (ff instanceof ExtensionFileFilter) {
50- fn += "." + ((ExtensionFileFilter)ff).defaultExtension;
51- } else {
52- fn += extension;
53- }
54- file = new File(fn);
55- }
56- }
57- if(file == null || (file.exists() && 1 != new ExtendedDialog(Main.parent,
58- tr("Overwrite"), tr("File exists. Overwrite?"),
59- new String[] {tr("Overwrite"), tr("Cancel")},
60- new String[] {"save_as.png", "cancel.png"}).getValue()))
61- return null;
62- return file;
63- }
64 }
65Index: src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
66===================================================================
67--- src/org/openstreetmap/josm/actions/ExtensionFileFilter.java (revision 1946)
68+++ src/org/openstreetmap/josm/actions/ExtensionFileFilter.java (working copy)
69@@ -7,10 +7,15 @@
70
71 import javax.swing.filechooser.FileFilter;
72
73+import org.openstreetmap.josm.io.FileExporter;
74 import org.openstreetmap.josm.io.FileImporter;
75+import org.openstreetmap.josm.io.GpxExporter;
76 import org.openstreetmap.josm.io.GpxImporter;
77 import org.openstreetmap.josm.io.NMEAImporter;
78+import org.openstreetmap.josm.io.OsmBzip2Exporter;
79 import org.openstreetmap.josm.io.OsmBzip2Importer;
80+import org.openstreetmap.josm.io.OsmExporter;
81+import org.openstreetmap.josm.io.OsmGzipExporter;
82 import org.openstreetmap.josm.io.OsmGzipImporter;
83 import org.openstreetmap.josm.io.OsmImporter;
84
85@@ -28,6 +33,10 @@
86 public static ArrayList<FileImporter> importers = new ArrayList<FileImporter>(Arrays.asList(new OsmImporter(),
87 new OsmGzipImporter(), new OsmBzip2Importer(), new GpxImporter(), new NMEAImporter()));
88
89+ // list of supported export formats
90+ public static ArrayList<FileExporter> exporters = new ArrayList<FileExporter>(Arrays.asList(new GpxExporter(),
91+ new OsmExporter(), new OsmGzipExporter(), new OsmBzip2Exporter()));
92+
93 /**
94 * Construct an extension file filter by giving the extension to check after.
95 *
96Index: src/org/openstreetmap/josm/actions/GpxExportAction.java
97===================================================================
98--- src/org/openstreetmap/josm/actions/GpxExportAction.java (revision 1946)
99+++ src/org/openstreetmap/josm/actions/GpxExportAction.java (working copy)
100@@ -1,39 +1,22 @@
101 // License: GPL. Copyright 2007 by Immanuel Scholz and others
102 package org.openstreetmap.josm.actions;
103
104+import static org.openstreetmap.josm.actions.SaveActionBase.createAndOpenSaveFileChooser;
105 import static org.openstreetmap.josm.tools.I18n.tr;
106
107-import java.awt.GridBagLayout;
108 import java.awt.event.ActionEvent;
109-import java.awt.event.ActionListener;
110-import java.awt.event.KeyAdapter;
111 import java.awt.event.KeyEvent;
112 import java.io.File;
113-import java.io.FileOutputStream;
114 import java.io.IOException;
115-import java.util.Calendar;
116
117-import javax.swing.JButton;
118-import javax.swing.JCheckBox;
119-import javax.swing.JFileChooser;
120-import javax.swing.JLabel;
121-import javax.swing.JList;
122 import javax.swing.JOptionPane;
123-import javax.swing.JPanel;
124-import javax.swing.JScrollPane;
125-import javax.swing.JTextArea;
126-import javax.swing.JTextField;
127-import javax.swing.ListSelectionModel;
128
129 import org.openstreetmap.josm.Main;
130-import org.openstreetmap.josm.data.gpx.GpxData;
131-import org.openstreetmap.josm.gui.ExtendedDialog;
132 import org.openstreetmap.josm.gui.OptionPaneUtil;
133 import org.openstreetmap.josm.gui.layer.GpxLayer;
134 import org.openstreetmap.josm.gui.layer.Layer;
135 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
136-import org.openstreetmap.josm.io.GpxWriter;
137-import org.openstreetmap.josm.tools.GBC;
138+import org.openstreetmap.josm.io.FileExporter;
139 import org.openstreetmap.josm.tools.Shortcut;
140
141 /**
142@@ -41,7 +24,6 @@
143 */
144 public class GpxExportAction extends DiskAccessAction {
145
146- 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>";
147
148 public GpxExportAction() {
149 super(tr("Export to GPX..."), "exportgpx", tr("Export the data to GPX file."),
150@@ -90,255 +72,18 @@
151 if (! (layer instanceof OsmDataLayer) && ! (layer instanceof GpxLayer))
152 throw new IllegalArgumentException(tr("expected instance of OsmDataLayer or GpxLayer. Got ''{0}''.", layer.getClass().getName()));
153
154- JFileChooser fc = createAndOpenFileChooser(false, false, null);
155- if (fc == null)
156- return;
157- File file = fc.getSelectedFile();
158+ File file = createAndOpenSaveFileChooser(tr("Export GPX file"), ".gpx");
159 if (file == null)
160 return;
161
162- exportGpx(file, layer);
163- }
164-
165- /**
166- * Exports a layer to a file.
167- *
168- * <code>layer</code> must not be null. <code>layer</code> must be an instance of
169- * {@see OsmDataLayer} or {@see GpxLayer}.
170- *
171- * @param layer the layer
172- * @exception IllegalArgumentException thrown if layer is null
173- * @exception IllegalArgumentException thrown if layer is neither an instance of {@see OsmDataLayer}
174- * nor of {@see GpxLayer}
175- */
176-
177- public void exportGpx(File file, Layer layer) {
178- if (layer == null)
179- throw new IllegalArgumentException(tr("paramenter ''{0}'' must not be null", "layer"));
180- if (! (layer instanceof OsmDataLayer) && ! (layer instanceof GpxLayer))
181- throw new IllegalArgumentException(tr("expected instance of OsmDataLayer or GpxLayer. Got ''{0}''.", layer.getClass().getName()));
182- if (file == null)
183- throw new IllegalArgumentException(tr("paramenter ''{0}'' must not be null", "file"));
184-
185- String fn = file.getPath();
186- if (fn.indexOf('.') == -1) {
187- fn += ".gpx";
188- file = new File(fn);
189- }
190-
191- // open the dialog asking for options
192- JPanel p = new JPanel(new GridBagLayout());
193-
194- p.add(new JLabel(tr("gps track description")), GBC.eol());
195- JTextArea desc = new JTextArea(3,40);
196- desc.setWrapStyleWord(true);
197- desc.setLineWrap(true);
198- p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH));
199-
200- JCheckBox author = new JCheckBox(tr("Add author information"), Main.pref.getBoolean("lastAddAuthor", true));
201- author.setSelected(true);
202- p.add(author, GBC.eol());
203- JLabel nameLabel = new JLabel(tr("Real name"));
204- p.add(nameLabel, GBC.std().insets(10,0,5,0));
205- JTextField authorName = new JTextField(Main.pref.get("lastAuthorName"));
206- p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL));
207- JLabel emailLabel = new JLabel(tr("E-Mail"));
208- p.add(emailLabel, GBC.std().insets(10,0,5,0));
209- JTextField email = new JTextField(Main.pref.get("osm-server.username"));
210- p.add(email, GBC.eol().fill(GBC.HORIZONTAL));
211- JLabel copyrightLabel = new JLabel(tr("Copyright (URL)"));
212- p.add(copyrightLabel, GBC.std().insets(10,0,5,0));
213- JTextField copyright = new JTextField();
214- p.add(copyright, GBC.std().fill(GBC.HORIZONTAL));
215- JButton predefined = new JButton(tr("Predefined"));
216- p.add(predefined, GBC.eol().insets(5,0,0,0));
217- JLabel copyrightYearLabel = new JLabel(tr("Copyright year"));
218- p.add(copyrightYearLabel, GBC.std().insets(10,0,5,5));
219- JTextField copyrightYear = new JTextField("");
220- p.add(copyrightYear, GBC.eol().fill(GBC.HORIZONTAL));
221- JLabel warning = new JLabel("<html><font size='-2'>&nbsp;</html");
222- p.add(warning, GBC.eol().fill(GBC.HORIZONTAL).insets(15,0,0,0));
223- addDependencies(author, authorName, email, copyright, predefined, copyrightYear, nameLabel, emailLabel, copyrightLabel, copyrightYearLabel, warning);
224-
225- // if the user name is not the email address, but the osm user name
226- // move it from the email textfield to the author textfield
227- if(!email.getText().contains("@")) {
228- authorName.setText(email.getText());
229- email.setText("");
230- }
231-
232- p.add(new JLabel(tr("Keywords")), GBC.eol());
233- JTextField keywords = new JTextField();
234- p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
235-
236- int answer = new ExtendedDialog(Main.parent,
237- tr("Export options"),
238- p,
239- new String[] {tr("Export and Save"), tr("Cancel")},
240- new String[] {"exportgpx.png", "cancel.png"}).getValue();
241- if (answer != 1)
242- return;
243-
244- Main.pref.put("lastAddAuthor", author.isSelected());
245- if (authorName.getText().length() != 0) {
246- Main.pref.put("lastAuthorName", authorName.getText());
247- }
248- if (copyright.getText().length() != 0) {
249- Main.pref.put("lastCopyright", copyright.getText());
250- }
251-
252- GpxData gpxData;
253- if (layer instanceof OsmDataLayer) {
254- gpxData = ((OsmDataLayer)layer).toGpxData();
255- } else if (layer instanceof GpxLayer) {
256- gpxData = ((GpxLayer)layer).data;
257- } else {
258- gpxData = OsmDataLayer.toGpxData(getCurrentDataSet(), file);
259- }
260-
261- // add author and copyright details to the gpx data
262- if(author.isSelected()) {
263- if(authorName.getText().length() > 0) {
264- gpxData.attr.put(GpxData.META_AUTHOR_NAME, authorName.getText());
265- gpxData.attr.put(GpxData.META_COPYRIGHT_AUTHOR, authorName.getText());
266- }
267- if(email.getText().length() > 0) {
268- gpxData.attr.put(GpxData.META_AUTHOR_EMAIL, email.getText());
269- }
270- if(copyright.getText().length() > 0) {
271- gpxData.attr.put(GpxData.META_COPYRIGHT_LICENSE, copyright.getText());
272- }
273- if(copyrightYear.getText().length() > 0) {
274- gpxData.attr.put(GpxData.META_COPYRIGHT_YEAR, copyrightYear.getText());
275- }
276- }
277-
278- // add the description to the gpx data
279- if(desc.getText().length() > 0) {
280- gpxData.attr.put(GpxData.META_DESC, desc.getText());
281- }
282-
283- // add keywords to the gpx data
284- if(keywords.getText().length() > 0) {
285- gpxData.attr.put(GpxData.META_KEYWORDS, keywords.getText());
286- }
287-
288- try {
289- FileOutputStream fo = new FileOutputStream(file);
290- new GpxWriter(fo).write(gpxData);
291- fo.flush();
292- fo.close();
293- } catch (IOException x) {
294- x.printStackTrace();
295- OptionPaneUtil.showMessageDialog(
296- Main.parent,
297- tr("Error while exporting {0}:\n{1}", fn,x.getMessage()),
298- tr("Error"),
299- JOptionPane.ERROR_MESSAGE
300- );
301- }
302- }
303-
304- /**
305- * Add all those listeners to handle the enable state of the fields.
306- * @param copyrightYearLabel
307- * @param copyrightLabel
308- * @param emailLabel
309- * @param nameLabel
310- * @param warning
311- */
312- private static void addDependencies(
313- final JCheckBox author,
314- final JTextField authorName,
315- final JTextField email,
316- final JTextField copyright,
317- final JButton predefined,
318- final JTextField copyrightYear,
319- final JLabel nameLabel,
320- final JLabel emailLabel,
321- final JLabel copyrightLabel,
322- final JLabel copyrightYearLabel,
323- final JLabel warning) {
324-
325- ActionListener authorActionListener = new ActionListener(){
326- public void actionPerformed(ActionEvent e) {
327- boolean b = author.isSelected();
328- authorName.setEnabled(b);
329- email.setEnabled(b);
330- nameLabel.setEnabled(b);
331- emailLabel.setEnabled(b);
332- authorName.setText(b ? Main.pref.get("lastAuthorName") : "");
333- email.setText(b ? Main.pref.get("osm-server.username") : "");
334-
335- boolean authorSet = authorName.getText().length() != 0;
336- enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b && authorSet);
337- }
338- };
339- author.addActionListener(authorActionListener);
340-
341- KeyAdapter authorNameListener = new KeyAdapter(){
342- @Override public void keyReleased(KeyEvent e) {
343- boolean b = authorName.getText().length()!=0 && author.isSelected();
344- enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b);
345- }
346- };
347- authorName.addKeyListener(authorNameListener);
348-
349- predefined.addActionListener(new ActionListener(){
350- public void actionPerformed(ActionEvent e) {
351- JList l = new JList(new String[]{"Creative Commons By-SA", "public domain", "GNU Lesser Public License (LGPL)", "BSD License (MIT/X11)"});
352- l.setVisibleRowCount(4);
353- l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
354- int answer = OptionPaneUtil.showConfirmationDialog(
355- Main.parent,
356- new JScrollPane(l),
357- tr("Choose a predefined license"),
358- JOptionPane.OK_CANCEL_OPTION,
359- JOptionPane.QUESTION_MESSAGE
360- );
361- if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1)
362- return;
363- final String[] urls = {
364- "http://creativecommons.org/licenses/by-sa/2.5",
365- "public domain",
366- "http://www.gnu.org/copyleft/lesser.html",
367- "http://www.opensource.org/licenses/bsd-license.php"};
368- String license = "";
369- for (int i : l.getSelectedIndices()) {
370- if (i == 1) {
371- license = "public domain";
372- break;
373- }
374- license += license.length()==0 ? urls[i] : ", "+urls[i];
375+ for (FileExporter exporter : ExtensionFileFilter.exporters) {
376+ if (exporter.acceptFile(file, layer)) {
377+ try {
378+ exporter.exportData(file, layer);
379+ } catch (IOException e1) {
380+ e1.printStackTrace();
381 }
382- copyright.setText(license);
383- copyright.setCaretPosition(0);
384 }
385- });
386-
387- authorActionListener.actionPerformed(null);
388- authorNameListener.keyReleased(null);
389- }
390-
391- private static void enableCopyright(final JTextField copyright, final JButton predefined, final JTextField copyrightYear, final JLabel copyrightLabel, final JLabel copyrightYearLabel, final JLabel warning, boolean enable) {
392- copyright.setEnabled(enable);
393- predefined.setEnabled(enable);
394- copyrightYear.setEnabled(enable);
395- copyrightLabel.setEnabled(enable);
396- copyrightYearLabel.setEnabled(enable);
397- warning.setText(enable ? warningGpl : "<html><font size='-2'>&nbsp;</html");
398-
399- if (enable && copyrightYear.getText().length()==0) {
400- copyrightYear.setText(enable ? Integer.toString(Calendar.getInstance().get(Calendar.YEAR)) : "");
401- } else if (!enable) {
402- copyrightYear.setText("");
403- }
404-
405- if (enable && copyright.getText().length()==0) {
406- copyright.setText(enable ? Main.pref.get("lastCopyright", "http://creativecommons.org/licenses/by-sa/2.5") : "");
407- copyright.setCaretPosition(0);
408- } else if (!enable) {
409- copyright.setText("");
410 }
411 }
412
413Index: src/org/openstreetmap/josm/actions/SaveActionBase.java
414===================================================================
415--- src/org/openstreetmap/josm/actions/SaveActionBase.java (revision 1946)
416+++ src/org/openstreetmap/josm/actions/SaveActionBase.java (working copy)
417@@ -5,19 +5,12 @@
418
419 import java.awt.event.ActionEvent;
420 import java.io.File;
421-import java.io.FileInputStream;
422-import java.io.FileNotFoundException;
423-import java.io.FileOutputStream;
424 import java.io.IOException;
425-import java.io.OutputStream;
426-import java.io.OutputStreamWriter;
427-import java.io.PrintWriter;
428-import java.io.Writer;
429-import java.util.zip.GZIPOutputStream;
430
431+import javax.swing.JFileChooser;
432 import javax.swing.JOptionPane;
433+import javax.swing.filechooser.FileFilter;
434
435-import org.apache.tools.bzip2.CBZip2OutputStream;
436 import org.openstreetmap.josm.Main;
437 import org.openstreetmap.josm.data.conflict.ConflictCollection;
438 import org.openstreetmap.josm.data.osm.OsmPrimitive;
439@@ -26,12 +19,7 @@
440 import org.openstreetmap.josm.gui.layer.GpxLayer;
441 import org.openstreetmap.josm.gui.layer.Layer;
442 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
443-import org.openstreetmap.josm.io.GpxImporter;
444-import org.openstreetmap.josm.io.GpxWriter;
445-import org.openstreetmap.josm.io.OsmBzip2Importer;
446-import org.openstreetmap.josm.io.OsmGzipImporter;
447-import org.openstreetmap.josm.io.OsmImporter;
448-import org.openstreetmap.josm.io.OsmWriter;
449+import org.openstreetmap.josm.io.FileExporter;
450 import org.openstreetmap.josm.tools.Shortcut;
451
452 public abstract class SaveActionBase extends DiskAccessAction {
453@@ -69,11 +57,26 @@
454 if (file == null)
455 return false;
456
457- save(file, layer);
458-
459- layer.setName(file.getName());
460- layer.setAssociatedFile(file);
461- Main.parent.repaint();
462+ try {
463+ boolean exported = false;
464+ for (FileExporter exporter : ExtensionFileFilter.exporters) {
465+ if (exporter.acceptFile(file, layer)) {
466+ exporter.exportData(file, layer);
467+ exported = true;
468+ }
469+ }
470+ if (!exported) {
471+ OptionPaneUtil.showMessageDialog(Main.parent, tr("No Exporter found! Nothing saved."), tr("Warning"),
472+ JOptionPane.WARNING_MESSAGE);
473+ return false;
474+ }
475+ layer.setName(file.getName());
476+ layer.setAssociatedFile(file);
477+ Main.parent.repaint();
478+ } catch (IOException e) {
479+ e.printStackTrace();
480+ return false;
481+ }
482 return true;
483 }
484
485@@ -131,173 +134,6 @@
486 return createAndOpenSaveFileChooser(tr("Save Layer"), ".lay");
487 }
488
489- private static void copy(File src, File dst) throws IOException {
490- FileInputStream srcStream;
491- FileOutputStream dstStream;
492- try {
493- srcStream = new FileInputStream(src);
494- dstStream = new FileOutputStream(dst);
495- } catch (FileNotFoundException e) {
496- OptionPaneUtil.showMessageDialog(
497- Main.parent,
498- tr("Could not back up file. Exception is: {0}", e.getMessage()),
499- tr("Error"),
500- JOptionPane.ERROR_MESSAGE
501- );
502- return;
503- }
504- byte buf[] = new byte[1<<16];
505- int len;
506- while ((len = srcStream.read(buf)) != -1) {
507- dstStream.write(buf, 0, len);
508- }
509- srcStream.close();
510- dstStream.close();
511- }
512-
513- public static void save(File file, Layer layer) {
514- if (layer instanceof GpxLayer) {
515- save(file, (GpxLayer)layer);
516- ((GpxLayer)layer).data.storageFile = file;
517- } else if (layer instanceof OsmDataLayer) {
518- save(file, (OsmDataLayer)layer);
519- }
520- }
521-
522- public static void save(File file, OsmDataLayer layer) {
523- File tmpFile = null;
524- try {
525- GpxImporter gpxImExporter = new GpxImporter();
526- OsmImporter osmImExporter = new OsmImporter();
527- OsmGzipImporter osmGzipImporter = new OsmGzipImporter();
528- OsmBzip2Importer osmBzip2Importer = new OsmBzip2Importer();
529- if (gpxImExporter.acceptFile(file)) {
530- new GpxExportAction().exportGpx(file, layer);
531- } else if (osmImExporter.acceptFile(file)
532- || osmGzipImporter.acceptFile(file)
533- || osmBzip2Importer.acceptFile(file))
534- {
535- // use a tmp file because if something errors out in the
536- // process of writing the file, we might just end up with
537- // a truncated file. That can destroy lots of work.
538- if (file.exists()) {
539- tmpFile = new File(file.getPath() + "~");
540- copy(file, tmpFile);
541- }
542-
543- // create outputstream and wrap it with gzip or bzip, if necessary
544- OutputStream out = new FileOutputStream(file);
545- if(osmGzipImporter.acceptFile(file)) {
546- out = new GZIPOutputStream(out);
547- } else if(osmBzip2Importer.acceptFile(file)) {
548- out.write('B');
549- out.write('Z');
550- out = new CBZip2OutputStream(out);
551- }
552- Writer writer = new OutputStreamWriter(out, "UTF-8");
553-
554- OsmWriter w = new OsmWriter(new PrintWriter(writer), false, layer.data.version);
555- w.header();
556- w.writeDataSources(layer.data);
557- w.writeContent(layer.data);
558- w.footer();
559- w.close();
560- // FIXME - how to close?
561- if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) {
562- tmpFile.delete();
563- }
564- } else {
565- OptionPaneUtil.showMessageDialog(
566- Main.parent,
567- tr("Unknown file extension for file ''{0}''", file.toString()),
568- tr("Error"),
569- JOptionPane.ERROR_MESSAGE
570- );
571- return;
572- }
573- layer.cleanupAfterSaveToDisk();
574- } catch (IOException e) {
575- e.printStackTrace();
576- OptionPaneUtil.showMessageDialog(
577- Main.parent,
578- tr("<html>An error occurred while saving.<br>Error is: <br>{0}</html>", e.getMessage()),
579- tr("Error"),
580- JOptionPane.ERROR_MESSAGE
581- );
582-
583- try {
584- // if the file save failed, then the tempfile will not
585- // be deleted. So, restore the backup if we made one.
586- if (tmpFile != null && tmpFile.exists()) {
587- copy(tmpFile, file);
588- }
589- } catch (IOException e2) {
590- e2.printStackTrace();
591- OptionPaneUtil.showMessageDialog(
592- Main.parent,
593- tr("<html>An error occurred while restoring backup file.<br>Error is: <br>{0}</html>", e2.getMessage()),
594- tr("Error"),
595- JOptionPane.ERROR_MESSAGE
596- );
597- }
598- }
599- }
600-
601- public static void save(File file, GpxLayer layer) {
602- File tmpFile = null;
603- try {
604- GpxImporter gpxImExporter = new GpxImporter();
605- if (gpxImExporter.acceptFile(file)) {
606-
607- // use a tmp file because if something errors out in the
608- // process of writing the file, we might just end up with
609- // a truncated file. That can destroy lots of work.
610- if (file.exists()) {
611- tmpFile = new File(file.getPath() + "~");
612- copy(file, tmpFile);
613- }
614- FileOutputStream fo = new FileOutputStream(file);
615- new GpxWriter(fo).write(layer.data);
616- fo.flush();
617- fo.close();
618-
619- if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) {
620- tmpFile.delete();
621- }
622- } else {
623- OptionPaneUtil.showMessageDialog(
624- Main.parent,
625- tr("Unknown file extension."),
626- tr("Error"),
627- JOptionPane.ERROR_MESSAGE
628- );
629- return;
630- }
631- } catch (IOException e) {
632- e.printStackTrace();
633- OptionPaneUtil.showMessageDialog(
634- Main.parent,
635- tr("An error occurred while saving. Error is: {0}", e.getMessage()),
636- tr("Error"),
637- JOptionPane.ERROR_MESSAGE
638- );
639- }
640- try {
641- // if the file save failed, then the tempfile will not
642- // be deleted. So, restore the backup if we made one.
643- if (tmpFile != null && tmpFile.exists()) {
644- copy(tmpFile, file);
645- }
646- } catch (IOException e) {
647- e.printStackTrace();
648- OptionPaneUtil.showMessageDialog(
649- Main.parent,
650- tr("<html>An error occurred while restoring backup file.<br>Error is:<br>{0}</html>", e.getMessage()),
651- tr("Error"),
652- JOptionPane.ERROR_MESSAGE
653- );;
654- }
655- }
656
657 /**
658 * Check the data set if it would be empty on save. It is empty, if it contains
659@@ -333,4 +169,59 @@
660 Layer layer = Main.map.mapView.getActiveLayer();
661 setEnabled(layer instanceof OsmDataLayer || layer instanceof GpxLayer);
662 }
663+
664+ public static File createAndOpenSaveFileChooser(String title, String extension) {
665+ String curDir = Main.pref.get("lastDirectory");
666+ if (curDir.equals("")) {
667+ curDir = ".";
668+ }
669+ JFileChooser fc = new JFileChooser(new File(curDir));
670+ if (title != null) {
671+ fc.setDialogTitle(title);
672+ }
673+
674+ fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
675+ fc.setMultiSelectionEnabled(false);
676+ fc.setAcceptAllFileFilterUsed(false);
677+
678+ FileFilter defaultFilter = null;
679+ for (FileExporter exporter : ExtensionFileFilter.exporters) {
680+ fc.addChoosableFileFilter(exporter.filter);
681+ if (extension.endsWith(exporter.filter.defaultExtension)) {
682+ defaultFilter = exporter.filter;
683+ }
684+ }
685+ if (defaultFilter != null) {
686+ fc.setFileFilter(defaultFilter);
687+ }
688+
689+ int answer = fc.showSaveDialog(Main.parent);
690+ if (answer != JFileChooser.APPROVE_OPTION)
691+ return null;
692+
693+ if (!fc.getCurrentDirectory().getAbsolutePath().equals(curDir)) {
694+ Main.pref.put("lastDirectory", fc.getCurrentDirectory().getAbsolutePath());
695+ }
696+
697+ File file = fc.getSelectedFile();
698+ if(extension != null){
699+ String fn = file.getPath();
700+ if(fn.indexOf('.') == -1)
701+ {
702+ FileFilter ff = fc.getFileFilter();
703+ if (ff instanceof ExtensionFileFilter) {
704+ fn += "." + ((ExtensionFileFilter)ff).defaultExtension;
705+ } else {
706+ fn += extension;
707+ }
708+ file = new File(fn);
709+ }
710+ }
711+ if(file == null || (file.exists() && 1 != new ExtendedDialog(Main.parent,
712+ tr("Overwrite"), tr("File exists. Overwrite?"),
713+ new String[] {tr("Overwrite"), tr("Cancel")},
714+ new String[] {"save_as.png", "cancel.png"}).getValue()))
715+ return null;
716+ return file;
717+ }
718 }
719Index: src/org/openstreetmap/josm/io/FileExporter.java
720===================================================================
721--- src/org/openstreetmap/josm/io/FileExporter.java (revision 0)
722+++ src/org/openstreetmap/josm/io/FileExporter.java (revision 0)
723@@ -0,0 +1,26 @@
724+// License: GPL. For details, see LICENSE file.
725+package org.openstreetmap.josm.io;
726+
727+import static org.openstreetmap.josm.tools.I18n.tr;
728+
729+import java.io.File;
730+import java.io.IOException;
731+
732+import org.openstreetmap.josm.actions.ExtensionFileFilter;
733+import org.openstreetmap.josm.gui.layer.Layer;
734+
735+public abstract class FileExporter {
736+ public ExtensionFileFilter filter;
737+
738+ public FileExporter(ExtensionFileFilter filter) {
739+ this.filter = filter;
740+ }
741+
742+ public boolean acceptFile(File pathname, Layer layer) {
743+ return filter.acceptName(pathname.getName());
744+ }
745+
746+ public void exportData(File file, Layer layer) throws IOException {
747+ throw new IOException(tr("Could not export \"{0}\"", file.getName()));
748+ }
749+}
750Index: src/org/openstreetmap/josm/io/GpxExporter.java
751===================================================================
752--- src/org/openstreetmap/josm/io/GpxExporter.java (revision 0)
753+++ src/org/openstreetmap/josm/io/GpxExporter.java (revision 0)
754@@ -0,0 +1,291 @@
755+// License: GPL. For details, see LICENSE file.
756+package org.openstreetmap.josm.io;
757+
758+import static org.openstreetmap.josm.tools.I18n.tr;
759+
760+import java.awt.GridBagLayout;
761+import java.awt.event.ActionEvent;
762+import java.awt.event.ActionListener;
763+import java.awt.event.KeyAdapter;
764+import java.awt.event.KeyEvent;
765+import java.io.File;
766+import java.io.FileOutputStream;
767+import java.io.IOException;
768+import java.util.Calendar;
769+
770+import javax.swing.JButton;
771+import javax.swing.JCheckBox;
772+import javax.swing.JLabel;
773+import javax.swing.JList;
774+import javax.swing.JOptionPane;
775+import javax.swing.JPanel;
776+import javax.swing.JScrollPane;
777+import javax.swing.JTextArea;
778+import javax.swing.JTextField;
779+import javax.swing.ListSelectionModel;
780+
781+import org.openstreetmap.josm.Main;
782+import org.openstreetmap.josm.actions.ExtensionFileFilter;
783+import org.openstreetmap.josm.data.gpx.GpxData;
784+import org.openstreetmap.josm.data.osm.DataSet;
785+import org.openstreetmap.josm.gui.ExtendedDialog;
786+import org.openstreetmap.josm.gui.OptionPaneUtil;
787+import org.openstreetmap.josm.gui.layer.GpxLayer;
788+import org.openstreetmap.josm.gui.layer.Layer;
789+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
790+import org.openstreetmap.josm.tools.GBC;
791+
792+public class GpxExporter extends FileExporter {
793+ private final static String warningGpl = "<html><font color='red' size='-2'>"
794+ + tr("Note: GPL is not compatible with the OSM license. Do not upload GPL licensed tracks.") + "</html>";
795+
796+ public GpxExporter() {
797+ super(new ExtensionFileFilter("gpx,gpx.gz", "gpx", tr("GPX Files") + " (*.gpx *.gpx.gz)"));
798+ }
799+
800+ @Override
801+ public boolean acceptFile(File pathname, Layer layer) {
802+ if (!(layer instanceof OsmDataLayer) && !(layer instanceof GpxLayer))
803+ return false;
804+ return super.acceptFile(pathname, layer);
805+ }
806+
807+ @Override
808+ public void exportData(File file, Layer layer) throws IOException {
809+ if (layer == null)
810+ throw new IllegalArgumentException(tr("paramenter ''{0}'' must not be null", "layer"));
811+ if (!(layer instanceof OsmDataLayer) && !(layer instanceof GpxLayer))
812+ throw new IllegalArgumentException(tr("expected instance of OsmDataLayer or GpxLayer. Got ''{0}''.", layer
813+ .getClass().getName()));
814+ if (file == null)
815+ throw new IllegalArgumentException(tr("paramenter ''{0}'' must not be null", "file"));
816+
817+ String fn = file.getPath();
818+ if (fn.indexOf('.') == -1) {
819+ fn += ".gpx";
820+ file = new File(fn);
821+ }
822+
823+ // open the dialog asking for options
824+ JPanel p = new JPanel(new GridBagLayout());
825+
826+ p.add(new JLabel(tr("gps track description")), GBC.eol());
827+ JTextArea desc = new JTextArea(3, 40);
828+ desc.setWrapStyleWord(true);
829+ desc.setLineWrap(true);
830+ p.add(new JScrollPane(desc), GBC.eop().fill(GBC.BOTH));
831+
832+ JCheckBox author = new JCheckBox(tr("Add author information"), Main.pref.getBoolean("lastAddAuthor", true));
833+ author.setSelected(true);
834+ p.add(author, GBC.eol());
835+ JLabel nameLabel = new JLabel(tr("Real name"));
836+ p.add(nameLabel, GBC.std().insets(10, 0, 5, 0));
837+ JTextField authorName = new JTextField(Main.pref.get("lastAuthorName"));
838+ p.add(authorName, GBC.eol().fill(GBC.HORIZONTAL));
839+ JLabel emailLabel = new JLabel(tr("E-Mail"));
840+ p.add(emailLabel, GBC.std().insets(10, 0, 5, 0));
841+ JTextField email = new JTextField(Main.pref.get("osm-server.username"));
842+ p.add(email, GBC.eol().fill(GBC.HORIZONTAL));
843+ JLabel copyrightLabel = new JLabel(tr("Copyright (URL)"));
844+ p.add(copyrightLabel, GBC.std().insets(10, 0, 5, 0));
845+ JTextField copyright = new JTextField();
846+ p.add(copyright, GBC.std().fill(GBC.HORIZONTAL));
847+ JButton predefined = new JButton(tr("Predefined"));
848+ p.add(predefined, GBC.eol().insets(5, 0, 0, 0));
849+ JLabel copyrightYearLabel = new JLabel(tr("Copyright year"));
850+ p.add(copyrightYearLabel, GBC.std().insets(10, 0, 5, 5));
851+ JTextField copyrightYear = new JTextField("");
852+ p.add(copyrightYear, GBC.eol().fill(GBC.HORIZONTAL));
853+ JLabel warning = new JLabel("<html><font size='-2'>&nbsp;</html");
854+ p.add(warning, GBC.eol().fill(GBC.HORIZONTAL).insets(15, 0, 0, 0));
855+ addDependencies(author, authorName, email, copyright, predefined, copyrightYear, nameLabel, emailLabel,
856+ copyrightLabel, copyrightYearLabel, warning);
857+
858+ // if the user name is not the email address, but the osm user name
859+ // move it from the email textfield to the author textfield
860+ if (!email.getText().contains("@")) {
861+ authorName.setText(email.getText());
862+ email.setText("");
863+ }
864+
865+ p.add(new JLabel(tr("Keywords")), GBC.eol());
866+ JTextField keywords = new JTextField();
867+ p.add(keywords, GBC.eop().fill(GBC.HORIZONTAL));
868+
869+ int answer = new ExtendedDialog(Main.parent, tr("Export options"), p, new String[] { tr("Export and Save"),
870+ tr("Cancel") }, new String[] { "exportgpx.png", "cancel.png" }).getValue();
871+ if (answer != 1)
872+ return;
873+
874+ Main.pref.put("lastAddAuthor", author.isSelected());
875+ if (authorName.getText().length() != 0) {
876+ Main.pref.put("lastAuthorName", authorName.getText());
877+ }
878+ if (copyright.getText().length() != 0) {
879+ Main.pref.put("lastCopyright", copyright.getText());
880+ }
881+
882+ GpxData gpxData;
883+ if (layer instanceof OsmDataLayer) {
884+ gpxData = ((OsmDataLayer) layer).toGpxData();
885+ } else if (layer instanceof GpxLayer) {
886+ gpxData = ((GpxLayer) layer).data;
887+ } else {
888+ gpxData = OsmDataLayer.toGpxData(getCurrentDataSet(), file);
889+ }
890+
891+ // add author and copyright details to the gpx data
892+ if (author.isSelected()) {
893+ if (authorName.getText().length() > 0) {
894+ gpxData.attr.put(GpxData.META_AUTHOR_NAME, authorName.getText());
895+ gpxData.attr.put(GpxData.META_COPYRIGHT_AUTHOR, authorName.getText());
896+ }
897+ if (email.getText().length() > 0) {
898+ gpxData.attr.put(GpxData.META_AUTHOR_EMAIL, email.getText());
899+ }
900+ if (copyright.getText().length() > 0) {
901+ gpxData.attr.put(GpxData.META_COPYRIGHT_LICENSE, copyright.getText());
902+ }
903+ if (copyrightYear.getText().length() > 0) {
904+ gpxData.attr.put(GpxData.META_COPYRIGHT_YEAR, copyrightYear.getText());
905+ }
906+ }
907+
908+ // add the description to the gpx data
909+ if (desc.getText().length() > 0) {
910+ gpxData.attr.put(GpxData.META_DESC, desc.getText());
911+ }
912+
913+ // add keywords to the gpx data
914+ if (keywords.getText().length() > 0) {
915+ gpxData.attr.put(GpxData.META_KEYWORDS, keywords.getText());
916+ }
917+
918+ try {
919+ FileOutputStream fo = new FileOutputStream(file);
920+ new GpxWriter(fo).write(gpxData);
921+ fo.flush();
922+ fo.close();
923+ } catch (IOException x) {
924+ x.printStackTrace();
925+ OptionPaneUtil.showMessageDialog(Main.parent, tr("Error while exporting {0}:\n{1}", fn, x.getMessage()),
926+ tr("Error"), JOptionPane.ERROR_MESSAGE);
927+ }
928+
929+ }
930+
931+ private static void enableCopyright(final JTextField copyright, final JButton predefined,
932+ final JTextField copyrightYear, final JLabel copyrightLabel, final JLabel copyrightYearLabel,
933+ final JLabel warning, boolean enable) {
934+ copyright.setEnabled(enable);
935+ predefined.setEnabled(enable);
936+ copyrightYear.setEnabled(enable);
937+ copyrightLabel.setEnabled(enable);
938+ copyrightYearLabel.setEnabled(enable);
939+ warning.setText(enable ? warningGpl : "<html><font size='-2'>&nbsp;</html");
940+
941+ if (enable && copyrightYear.getText().length()==0) {
942+ copyrightYear.setText(enable ? Integer.toString(Calendar.getInstance().get(Calendar.YEAR)) : "");
943+ } else if (!enable) {
944+ copyrightYear.setText("");
945+ }
946+
947+ if (enable && copyright.getText().length()==0) {
948+ copyright.setText(enable ? Main.pref.get("lastCopyright", "http://creativecommons.org/licenses/by-sa/2.5") : "");
949+ copyright.setCaretPosition(0);
950+ } else if (!enable) {
951+ copyright.setText("");
952+ }
953+ }
954+
955+ /**
956+ * Add all those listeners to handle the enable state of the fields.
957+ * @param copyrightYearLabel
958+ * @param copyrightLabel
959+ * @param emailLabel
960+ * @param nameLabel
961+ * @param warning
962+ */
963+ private static void addDependencies(
964+ final JCheckBox author,
965+ final JTextField authorName,
966+ final JTextField email,
967+ final JTextField copyright,
968+ final JButton predefined,
969+ final JTextField copyrightYear,
970+ final JLabel nameLabel,
971+ final JLabel emailLabel,
972+ final JLabel copyrightLabel,
973+ final JLabel copyrightYearLabel,
974+ final JLabel warning) {
975+
976+ ActionListener authorActionListener = new ActionListener(){
977+ public void actionPerformed(ActionEvent e) {
978+ boolean b = author.isSelected();
979+ authorName.setEnabled(b);
980+ email.setEnabled(b);
981+ nameLabel.setEnabled(b);
982+ emailLabel.setEnabled(b);
983+ authorName.setText(b ? Main.pref.get("lastAuthorName") : "");
984+ email.setText(b ? Main.pref.get("osm-server.username") : "");
985+
986+ boolean authorSet = authorName.getText().length() != 0;
987+ GpxExporter.enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b && authorSet);
988+ }
989+ };
990+ author.addActionListener(authorActionListener);
991+
992+ KeyAdapter authorNameListener = new KeyAdapter(){
993+ @Override public void keyReleased(KeyEvent e) {
994+ boolean b = authorName.getText().length()!=0 && author.isSelected();
995+ GpxExporter.enableCopyright(copyright, predefined, copyrightYear, copyrightLabel, copyrightYearLabel, warning, b);
996+ }
997+ };
998+ authorName.addKeyListener(authorNameListener);
999+
1000+ predefined.addActionListener(new ActionListener(){
1001+ public void actionPerformed(ActionEvent e) {
1002+ JList l = new JList(new String[]{"Creative Commons By-SA", "public domain", "GNU Lesser Public License (LGPL)", "BSD License (MIT/X11)"});
1003+ l.setVisibleRowCount(4);
1004+ l.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
1005+ int answer = OptionPaneUtil.showConfirmationDialog(
1006+ Main.parent,
1007+ new JScrollPane(l),
1008+ tr("Choose a predefined license"),
1009+ JOptionPane.OK_CANCEL_OPTION,
1010+ JOptionPane.QUESTION_MESSAGE
1011+ );
1012+ if (answer != JOptionPane.OK_OPTION || l.getSelectedIndex() == -1)
1013+ return;
1014+ final String[] urls = {
1015+ "http://creativecommons.org/licenses/by-sa/2.5",
1016+ "public domain",
1017+ "http://www.gnu.org/copyleft/lesser.html",
1018+ "http://www.opensource.org/licenses/bsd-license.php"};
1019+ String license = "";
1020+ for (int i : l.getSelectedIndices()) {
1021+ if (i == 1) {
1022+ license = "public domain";
1023+ break;
1024+ }
1025+ license += license.length()==0 ? urls[i] : ", "+urls[i];
1026+ }
1027+ copyright.setText(license);
1028+ copyright.setCaretPosition(0);
1029+ }
1030+ });
1031+
1032+ authorActionListener.actionPerformed(null);
1033+ authorNameListener.keyReleased(null);
1034+ }
1035+
1036+ /**
1037+ * Replies the current dataset
1038+ *
1039+ * @return the current dataset. null, if no current dataset exists
1040+ */
1041+ private DataSet getCurrentDataSet() {
1042+ return Main.main.getCurrentDataSet();
1043+ }
1044+
1045+}
1046Index: src/org/openstreetmap/josm/io/OsmBzip2Exporter.java
1047===================================================================
1048--- src/org/openstreetmap/josm/io/OsmBzip2Exporter.java (revision 0)
1049+++ src/org/openstreetmap/josm/io/OsmBzip2Exporter.java (revision 0)
1050@@ -0,0 +1,29 @@
1051+// License: GPL. For details, see LICENSE file.
1052+package org.openstreetmap.josm.io;
1053+
1054+import static org.openstreetmap.josm.tools.I18n.tr;
1055+
1056+import java.io.File;
1057+import java.io.FileNotFoundException;
1058+import java.io.FileOutputStream;
1059+import java.io.IOException;
1060+import java.io.OutputStream;
1061+
1062+import org.apache.tools.bzip2.CBZip2OutputStream;
1063+import org.openstreetmap.josm.actions.ExtensionFileFilter;
1064+public class OsmBzip2Exporter extends OsmExporter {
1065+
1066+ public OsmBzip2Exporter() {
1067+ super(new ExtensionFileFilter("osm.bz2, osm.bz", "osm.bz2", tr("OSM Server Files bzip2 compressed")
1068+ + " (*.osm.bz2 *.osm.bz)"));
1069+ }
1070+
1071+ @Override
1072+ protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException {
1073+ OutputStream out = new FileOutputStream(file);
1074+ out.write('B');
1075+ out.write('Z');
1076+ out = new CBZip2OutputStream(out);
1077+ return out;
1078+ }
1079+}
1080Index: src/org/openstreetmap/josm/io/OsmExporter.java
1081===================================================================
1082--- src/org/openstreetmap/josm/io/OsmExporter.java (revision 0)
1083+++ src/org/openstreetmap/josm/io/OsmExporter.java (revision 0)
1084@@ -0,0 +1,127 @@
1085+// License: GPL. For details, see LICENSE file.
1086+package org.openstreetmap.josm.io;
1087+
1088+import static org.openstreetmap.josm.tools.I18n.tr;
1089+
1090+import java.io.File;
1091+import java.io.FileInputStream;
1092+import java.io.FileNotFoundException;
1093+import java.io.FileOutputStream;
1094+import java.io.IOException;
1095+import java.io.OutputStream;
1096+import java.io.OutputStreamWriter;
1097+import java.io.PrintWriter;
1098+import java.io.Writer;
1099+
1100+import javax.swing.JOptionPane;
1101+
1102+import org.openstreetmap.josm.Main;
1103+import org.openstreetmap.josm.actions.ExtensionFileFilter;
1104+import org.openstreetmap.josm.gui.OptionPaneUtil;
1105+import org.openstreetmap.josm.gui.layer.Layer;
1106+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
1107+
1108+public class OsmExporter extends FileExporter {
1109+
1110+ public OsmExporter() {
1111+ super(new ExtensionFileFilter("osm,xml", "osm", tr("OSM Server Files") + " (*.osm *.xml)"));
1112+ }
1113+
1114+ public OsmExporter(ExtensionFileFilter filter) {
1115+ super(filter);
1116+ }
1117+
1118+ @Override
1119+ public boolean acceptFile(File pathname, Layer layer) {
1120+ if (!(layer instanceof OsmDataLayer))
1121+ return false;
1122+ return super.acceptFile(pathname, layer);
1123+ }
1124+
1125+ @Override
1126+ public void exportData(File file, Layer layer) throws IOException {
1127+ if (layer instanceof OsmDataLayer) {
1128+ save(file, (OsmDataLayer) layer);
1129+ } else
1130+ throw new IllegalArgumentException(tr("Expected instance of OsmDataLayer. Got ''{0}''.", layer
1131+ .getClass().getName()));
1132+ }
1133+
1134+ protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException {
1135+ return new FileOutputStream(file);
1136+ }
1137+
1138+ private void save(File file, OsmDataLayer layer) {
1139+ File tmpFile = null;
1140+ try {
1141+ // use a tmp file because if something errors out in the
1142+ // process of writing the file, we might just end up with
1143+ // a truncated file. That can destroy lots of work.
1144+ if (file.exists()) {
1145+ tmpFile = new File(file.getPath() + "~");
1146+ copy(file, tmpFile);
1147+ }
1148+
1149+ // create outputstream and wrap it with gzip or bzip, if necessary
1150+ OutputStream out = getOutputStream(file);
1151+ Writer writer = new OutputStreamWriter(out, "UTF-8");
1152+
1153+ OsmWriter w = new OsmWriter(new PrintWriter(writer), false, layer.data.version);
1154+ w.header();
1155+ w.writeDataSources(layer.data);
1156+ w.writeContent(layer.data);
1157+ w.footer();
1158+ w.close();
1159+ // FIXME - how to close?
1160+ if (!Main.pref.getBoolean("save.keepbackup") && (tmpFile != null)) {
1161+ tmpFile.delete();
1162+ }
1163+ layer.cleanupAfterSaveToDisk();
1164+ } catch (IOException e) {
1165+ e.printStackTrace();
1166+ OptionPaneUtil.showMessageDialog(
1167+ Main.parent,
1168+ tr("<html>An error occurred while saving.<br>Error is: <br>{0}</html>", e.getMessage()),
1169+ tr("Error"),
1170+ JOptionPane.ERROR_MESSAGE
1171+ );
1172+
1173+ try {
1174+ // if the file save failed, then the tempfile will not
1175+ // be deleted. So, restore the backup if we made one.
1176+ if (tmpFile != null && tmpFile.exists()) {
1177+ copy(tmpFile, file);
1178+ }
1179+ } catch (IOException e2) {
1180+ e2.printStackTrace();
1181+ OptionPaneUtil.showMessageDialog(
1182+ Main.parent,
1183+ tr("<html>An error occurred while restoring backup file.<br>Error is: <br>{0}</html>", e2.getMessage()),
1184+ tr("Error"),
1185+ JOptionPane.ERROR_MESSAGE
1186+ );
1187+ }
1188+ }
1189+ }
1190+
1191+ private void copy(File src, File dst) throws IOException {
1192+ FileInputStream srcStream;
1193+ FileOutputStream dstStream;
1194+ try {
1195+ srcStream = new FileInputStream(src);
1196+ dstStream = new FileOutputStream(dst);
1197+ } catch (FileNotFoundException e) {
1198+ OptionPaneUtil.showMessageDialog(Main.parent, tr("Could not back up file. Exception is: {0}", e
1199+ .getMessage()), tr("Error"), JOptionPane.ERROR_MESSAGE);
1200+ return;
1201+ }
1202+ byte buf[] = new byte[1 << 16];
1203+ int len;
1204+ while ((len = srcStream.read(buf)) != -1) {
1205+ dstStream.write(buf, 0, len);
1206+ }
1207+ srcStream.close();
1208+ dstStream.close();
1209+ }
1210+
1211+}
1212Index: src/org/openstreetmap/josm/io/OsmGzipExporter.java
1213===================================================================
1214--- src/org/openstreetmap/josm/io/OsmGzipExporter.java (revision 0)
1215+++ src/org/openstreetmap/josm/io/OsmGzipExporter.java (revision 0)
1216@@ -0,0 +1,25 @@
1217+// License: GPL. For details, see LICENSE file.
1218+package org.openstreetmap.josm.io;
1219+
1220+import static org.openstreetmap.josm.tools.I18n.tr;
1221+
1222+import java.io.File;
1223+import java.io.FileNotFoundException;
1224+import java.io.FileOutputStream;
1225+import java.io.IOException;
1226+import java.io.OutputStream;
1227+import java.util.zip.GZIPOutputStream;
1228+
1229+import org.openstreetmap.josm.actions.ExtensionFileFilter;
1230+public class OsmGzipExporter extends OsmExporter {
1231+
1232+ public OsmGzipExporter() {
1233+ super(new ExtensionFileFilter("osm.gz", "osm.gz", tr("OSM Server Files gzip compressed") + " (*.osm.gz)"));
1234+ }
1235+
1236+ @Override
1237+ protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException {
1238+ OutputStream out = new FileOutputStream(file);
1239+ return new GZIPOutputStream(out);
1240+ }
1241+}