source: josm/trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java@ 17379

Last change on this file since 17379 was 15070, checked in by Don-vip, 5 years ago

fix #17701, fix #17702 - add robustness when loading imagery layers from session

  • Property svn:eol-style set to native
File size: 9.0 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.tr;
6
7import java.awt.event.ActionEvent;
8import java.io.File;
9import java.io.IOException;
10import java.io.InputStream;
11import java.net.URI;
12import java.nio.file.Files;
13import java.nio.file.StandardCopyOption;
14import java.util.Arrays;
15import java.util.List;
16
17import javax.swing.JFileChooser;
18import javax.swing.JOptionPane;
19import javax.swing.SwingUtilities;
20
21import org.openstreetmap.josm.data.projection.ProjectionRegistry;
22import org.openstreetmap.josm.gui.HelpAwareOptionPane;
23import org.openstreetmap.josm.gui.MainApplication;
24import org.openstreetmap.josm.gui.Notification;
25import org.openstreetmap.josm.gui.PleaseWaitRunnable;
26import org.openstreetmap.josm.gui.layer.Layer;
27import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference;
28import org.openstreetmap.josm.gui.progress.ProgressMonitor;
29import org.openstreetmap.josm.gui.util.FileFilterAllFiles;
30import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
31import org.openstreetmap.josm.io.IllegalDataException;
32import org.openstreetmap.josm.io.session.SessionImporter;
33import org.openstreetmap.josm.io.session.SessionReader;
34import org.openstreetmap.josm.io.session.SessionReader.SessionProjectionChoiceData;
35import org.openstreetmap.josm.io.session.SessionReader.SessionViewportData;
36import org.openstreetmap.josm.tools.CheckParameterUtil;
37import org.openstreetmap.josm.tools.JosmRuntimeException;
38import org.openstreetmap.josm.tools.Logging;
39import org.openstreetmap.josm.tools.Utils;
40import org.openstreetmap.josm.tools.bugreport.ReportedException;
41
42/**
43 * Loads a JOSM session.
44 * @since 4668
45 */
46public class SessionLoadAction extends DiskAccessAction {
47
48 /**
49 * Constructs a new {@code SessionLoadAction}.
50 */
51 public SessionLoadAction() {
52 super(tr("Load Session"), "open", tr("Load a session from file."), null, true, "load-session", true);
53 setHelpId(ht("/Action/SessionLoad"));
54 }
55
56 @Override
57 public void actionPerformed(ActionEvent e) {
58 AbstractFileChooser fc = createAndOpenFileChooser(true, false, tr("Open session"),
59 Arrays.asList(SessionImporter.FILE_FILTER, FileFilterAllFiles.getInstance()),
60 SessionImporter.FILE_FILTER, JFileChooser.FILES_ONLY, "lastDirectory");
61 if (fc == null)
62 return;
63 File file = fc.getSelectedFile();
64 boolean zip = Utils.hasExtension(file, "joz");
65 MainApplication.worker.submit(new Loader(file, zip));
66 }
67
68 /**
69 * JOSM session loader
70 */
71 public static class Loader extends PleaseWaitRunnable {
72
73 private boolean canceled;
74 private File file;
75 private final URI uri;
76 private final InputStream is;
77 private final boolean zip;
78 private List<Layer> layers;
79 private Layer active;
80 private List<Runnable> postLoadTasks;
81 private SessionViewportData viewport;
82 private SessionProjectionChoiceData projectionChoice;
83
84 /**
85 * Constructs a new {@code Loader} for local session file.
86 * @param file The JOSM session file
87 * @param zip {@code true} if the file is a session archive file (*.joz)
88 */
89 public Loader(File file, boolean zip) {
90 super(tr("Loading session ''{0}''", file.getName()));
91 CheckParameterUtil.ensureParameterNotNull(file, "file");
92 this.file = file;
93 this.uri = null;
94 this.is = null;
95 this.zip = zip;
96 }
97
98 /**
99 * Constructs a new {@code Loader} for session file input stream (may be a remote file).
100 * @param is The input stream to session file
101 * @param uri The file URI
102 * @param zip {@code true} if the file is a session archive file (*.joz)
103 * @since 6245
104 */
105 public Loader(InputStream is, URI uri, boolean zip) {
106 super(tr("Loading session ''{0}''", uri));
107 CheckParameterUtil.ensureParameterNotNull(is, "is");
108 CheckParameterUtil.ensureParameterNotNull(uri, "uri");
109 this.file = null;
110 this.uri = uri;
111 this.is = is;
112 this.zip = zip;
113 }
114
115 @Override
116 public void cancel() {
117 canceled = true;
118 }
119
120 @Override
121 protected void finish() {
122 SwingUtilities.invokeLater(() -> {
123 if (canceled)
124 return;
125 if (projectionChoice != null) {
126 ProjectionPreference.setProjection(
127 projectionChoice.getProjectionChoiceId(),
128 projectionChoice.getSubPreferences(),
129 false);
130 }
131 addLayers();
132 runPostLoadTasks();
133 });
134 }
135
136 private void addLayers() {
137 if (layers != null && !layers.isEmpty()) {
138 boolean noMap = MainApplication.getMap() == null;
139 for (Layer l : layers) {
140 if (canceled)
141 return;
142 addLayer(l);
143 }
144 if (active != null) {
145 MainApplication.getLayerManager().setActiveLayer(active);
146 }
147 if (noMap && viewport != null) {
148 MainApplication.getMap().mapView.scheduleZoomTo(viewport.getEastNorthViewport(ProjectionRegistry.getProjection()));
149 }
150 }
151 }
152
153 /**
154 * Tries to add a new layer.
155 * @param l layer to add
156 * @return {@code true} if layer has been added, {@code false} if it wasn't needed or if an error occurred
157 */
158 static boolean addLayer(Layer l) {
159 // NoteImporter directly loads notes into current note layer
160 if (!MainApplication.getLayerManager().containsLayer(l)) {
161 try {
162 MainApplication.getLayerManager().addLayer(l);
163 } catch (ReportedException e) {
164 Logging.error(e);
165 new Notification(tr("Unable to add layer ''{0}'': {1}", l.getName(), e.getMessage()))
166 .setIcon(JOptionPane.ERROR_MESSAGE).setDuration(Notification.TIME_LONG).show();
167 if (MainApplication.getLayerManager().containsLayer(l)) {
168 MainApplication.getLayerManager().removeLayer(l);
169 }
170 return false;
171 }
172 }
173 return true;
174 }
175
176 private void runPostLoadTasks() {
177 if (postLoadTasks != null) {
178 for (Runnable task : postLoadTasks) {
179 if (canceled)
180 return;
181 if (task == null) {
182 continue;
183 }
184 task.run();
185 }
186 }
187 }
188
189 @Override
190 protected void realRun() {
191 try {
192 ProgressMonitor monitor = getProgressMonitor();
193 SessionReader reader = new SessionReader();
194 boolean tempFile = false;
195 try {
196 if (file == null) {
197 // Download and write entire joz file as a temp file on disk as we need random access later
198 file = File.createTempFile("session_", ".joz", Utils.getJosmTempDir());
199 tempFile = true;
200 Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
201 }
202 reader.loadSession(file, zip, monitor);
203 layers = reader.getLayers();
204 active = reader.getActive();
205 postLoadTasks = reader.getPostLoadTasks();
206 viewport = reader.getViewport();
207 projectionChoice = reader.getProjectionChoice();
208 } finally {
209 if (tempFile) {
210 Utils.deleteFile(file);
211 file = null;
212 }
213 }
214 } catch (IllegalDataException e) {
215 handleException(tr("Data Error"), e);
216 } catch (IOException e) {
217 handleException(tr("IO Error"), e);
218 } catch (JosmRuntimeException | IllegalArgumentException | IllegalStateException e) {
219 cancel();
220 throw e;
221 }
222 }
223
224 private void handleException(String dialogTitle, Exception e) {
225 Logging.error(e);
226 HelpAwareOptionPane.showMessageDialogInEDT(
227 MainApplication.getMainFrame(),
228 tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>",
229 uri != null ? uri : file.getName(), Utils.escapeReservedCharactersHTML(e.getMessage())),
230 dialogTitle,
231 JOptionPane.ERROR_MESSAGE,
232 null
233 );
234 cancel();
235 }
236 }
237}
Note: See TracBrowser for help on using the repository browser.