001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.actions; 003 004import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 005import static org.openstreetmap.josm.tools.I18n.tr; 006 007import java.awt.event.ActionEvent; 008import java.io.File; 009import java.io.IOException; 010import java.io.InputStream; 011import java.net.URI; 012import java.nio.file.Files; 013import java.nio.file.StandardCopyOption; 014import java.util.Arrays; 015import java.util.List; 016 017import javax.swing.JFileChooser; 018import javax.swing.JOptionPane; 019import javax.swing.SwingUtilities; 020 021import org.openstreetmap.josm.Main; 022import org.openstreetmap.josm.data.ViewportData; 023import org.openstreetmap.josm.gui.HelpAwareOptionPane; 024import org.openstreetmap.josm.gui.PleaseWaitRunnable; 025import org.openstreetmap.josm.gui.layer.Layer; 026import org.openstreetmap.josm.gui.progress.ProgressMonitor; 027import org.openstreetmap.josm.gui.util.FileFilterAllFiles; 028import org.openstreetmap.josm.gui.widgets.AbstractFileChooser; 029import org.openstreetmap.josm.io.IllegalDataException; 030import org.openstreetmap.josm.io.session.SessionImporter; 031import org.openstreetmap.josm.io.session.SessionReader; 032import org.openstreetmap.josm.tools.CheckParameterUtil; 033import org.openstreetmap.josm.tools.Utils; 034 035/** 036 * Loads a JOSM session. 037 * @since 4668 038 */ 039public class SessionLoadAction extends DiskAccessAction { 040 041 /** 042 * Constructs a new {@code SessionLoadAction}. 043 */ 044 public SessionLoadAction() { 045 super(tr("Load Session"), "open", tr("Load a session from file."), null, true, "load-session", true); 046 putValue("help", ht("/Action/SessionLoad")); 047 } 048 049 @Override 050 public void actionPerformed(ActionEvent e) { 051 AbstractFileChooser fc = createAndOpenFileChooser(true, false, tr("Open session"), 052 Arrays.asList(SessionImporter.FILE_FILTER, FileFilterAllFiles.getInstance()), 053 SessionImporter.FILE_FILTER, JFileChooser.FILES_ONLY, "lastDirectory"); 054 if (fc == null) 055 return; 056 File file = fc.getSelectedFile(); 057 boolean zip = Utils.hasExtension(file, "joz"); 058 Main.worker.submit(new Loader(file, zip)); 059 } 060 061 /** 062 * JOSM session loader 063 */ 064 public static class Loader extends PleaseWaitRunnable { 065 066 private boolean canceled; 067 private File file; 068 private final URI uri; 069 private final InputStream is; 070 private final boolean zip; 071 private List<Layer> layers; 072 private Layer active; 073 private List<Runnable> postLoadTasks; 074 private ViewportData viewport; 075 076 /** 077 * Constructs a new {@code Loader} for local session file. 078 * @param file The JOSM session file 079 * @param zip {@code true} if the file is a session archive file (*.joz) 080 */ 081 public Loader(File file, boolean zip) { 082 super(tr("Loading session ''{0}''", file.getName())); 083 CheckParameterUtil.ensureParameterNotNull(file, "file"); 084 this.file = file; 085 this.uri = null; 086 this.is = null; 087 this.zip = zip; 088 } 089 090 /** 091 * Constructs a new {@code Loader} for session file input stream (may be a remote file). 092 * @param is The input stream to session file 093 * @param uri The file URI 094 * @param zip {@code true} if the file is a session archive file (*.joz) 095 * @since 6245 096 */ 097 public Loader(InputStream is, URI uri, boolean zip) { 098 super(tr("Loading session ''{0}''", uri)); 099 CheckParameterUtil.ensureParameterNotNull(is, "is"); 100 CheckParameterUtil.ensureParameterNotNull(uri, "uri"); 101 this.file = null; 102 this.uri = uri; 103 this.is = is; 104 this.zip = zip; 105 } 106 107 @Override 108 public void cancel() { 109 canceled = true; 110 } 111 112 @Override 113 protected void finish() { 114 SwingUtilities.invokeLater(new Runnable() { 115 @Override 116 public void run() { 117 if (canceled) 118 return; 119 addLayers(); 120 runPostLoadTasks(); 121 } 122 }); 123 } 124 125 private void addLayers() { 126 if (layers != null && !layers.isEmpty()) { 127 Layer firstLayer = layers.get(0); 128 boolean noMap = Main.map == null; 129 if (noMap) { 130 Main.main.createMapFrame(firstLayer, viewport); 131 } 132 for (Layer l : layers) { 133 if (canceled) 134 return; 135 Main.main.addLayer(l, (ViewportData) null); 136 } 137 if (active != null) { 138 Main.getLayerManager().setActiveLayer(active); 139 } 140 if (noMap) { 141 Main.map.setVisible(true); 142 } 143 } 144 } 145 146 private void runPostLoadTasks() { 147 for (Runnable task : postLoadTasks) { 148 if (canceled) 149 return; 150 if (task == null) { 151 continue; 152 } 153 task.run(); 154 } 155 } 156 157 @Override 158 protected void realRun() { 159 try { 160 ProgressMonitor monitor = getProgressMonitor(); 161 SessionReader reader = new SessionReader(); 162 boolean tempFile = false; 163 try { 164 if (file == null) { 165 // Download and write entire joz file as a temp file on disk as we need random access later 166 file = File.createTempFile("session_", ".joz", Utils.getJosmTempDir()); 167 tempFile = true; 168 Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING); 169 } 170 reader.loadSession(file, zip, monitor); 171 layers = reader.getLayers(); 172 active = reader.getActive(); 173 postLoadTasks = reader.getPostLoadTasks(); 174 viewport = reader.getViewport(); 175 } finally { 176 if (tempFile) { 177 Utils.deleteFile(file); 178 file = null; 179 } 180 } 181 } catch (IllegalDataException e) { 182 handleException(tr("Data Error"), e); 183 } catch (IOException e) { 184 handleException(tr("IO Error"), e); 185 } catch (RuntimeException e) { 186 cancel(); 187 throw e; 188 } 189 } 190 191 private void handleException(String dialogTitle, Exception e) { 192 Main.error(e); 193 HelpAwareOptionPane.showMessageDialogInEDT( 194 Main.parent, 195 tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", 196 uri != null ? uri : file.getName(), e.getMessage()), 197 dialogTitle, 198 JOptionPane.ERROR_MESSAGE, 199 null 200 ); 201 cancel(); 202 } 203 } 204}