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) return; 055 File file = fc.getSelectedFile(); 056 boolean zip = Utils.hasExtension(file, "joz"); 057 Main.worker.submit(new Loader(file, zip)); 058 } 059 060 /** 061 * JOSM session loader 062 */ 063 public static class Loader extends PleaseWaitRunnable { 064 065 private boolean canceled; 066 private File file; 067 private final URI uri; 068 private final InputStream is; 069 private final boolean zip; 070 private List<Layer> layers; 071 private Layer active; 072 private List<Runnable> postLoadTasks; 073 private ViewportData viewport; 074 075 /** 076 * Constructs a new {@code Loader} for local session file. 077 * @param file The JOSM session file 078 * @param zip {@code true} if the file is a session archive file (*.joz) 079 */ 080 public Loader(File file, boolean zip) { 081 super(tr("Loading session ''{0}''", file.getName())); 082 CheckParameterUtil.ensureParameterNotNull(file, "file"); 083 this.file = file; 084 this.uri = null; 085 this.is = null; 086 this.zip = zip; 087 } 088 089 /** 090 * Constructs a new {@code Loader} for session file input stream (may be a remote file). 091 * @param is The input stream to session file 092 * @param uri The file URI 093 * @param zip {@code true} if the file is a session archive file (*.joz) 094 * @since 6245 095 */ 096 public Loader(InputStream is, URI uri, boolean zip) { 097 super(tr("Loading session ''{0}''", uri)); 098 CheckParameterUtil.ensureParameterNotNull(is, "is"); 099 CheckParameterUtil.ensureParameterNotNull(uri, "uri"); 100 this.file = null; 101 this.uri = uri; 102 this.is = is; 103 this.zip = zip; 104 } 105 106 @Override 107 public void cancel() { 108 canceled = true; 109 } 110 111 @Override 112 protected void finish() { 113 SwingUtilities.invokeLater(new Runnable() { 114 @Override 115 public void run() { 116 if (canceled) return; 117 if (!layers.isEmpty()) { 118 Layer firstLayer = layers.get(0); 119 boolean noMap = Main.map == null; 120 if (noMap) { 121 Main.main.createMapFrame(firstLayer, viewport); 122 } 123 for (Layer l : layers) { 124 if (canceled) return; 125 Main.main.addLayer(l, (ViewportData) null); 126 } 127 if (active != null) { 128 Main.map.mapView.setActiveLayer(active); 129 } 130 if (noMap) { 131 Main.map.setVisible(true); 132 } 133 } 134 for (Runnable task : postLoadTasks) { 135 if (canceled) return; 136 if (task == null) { 137 continue; 138 } 139 task.run(); 140 } 141 } 142 }); 143 } 144 145 @Override 146 protected void realRun() { 147 try { 148 ProgressMonitor monitor = getProgressMonitor(); 149 SessionReader reader = new SessionReader(); 150 boolean tempFile = false; 151 try { 152 if (file == null) { 153 // Download and write entire joz file as a temp file on disk as we need random access later 154 file = File.createTempFile("session_", ".joz", Utils.getJosmTempDir()); 155 tempFile = true; 156 Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING); 157 } 158 reader.loadSession(file, zip, monitor); 159 layers = reader.getLayers(); 160 active = reader.getActive(); 161 postLoadTasks = reader.getPostLoadTasks(); 162 viewport = reader.getViewport(); 163 } finally { 164 if (tempFile) { 165 Utils.deleteFile(file); 166 file = null; 167 } 168 } 169 } catch (IllegalDataException e) { 170 handleException(tr("Data Error"), e); 171 } catch (IOException e) { 172 handleException(tr("IO Error"), e); 173 } catch (Exception e) { 174 cancel(); 175 throw e; 176 } 177 } 178 179 private void handleException(String dialogTitle, Exception e) { 180 Main.error(e); 181 HelpAwareOptionPane.showMessageDialogInEDT( 182 Main.parent, 183 tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", 184 uri != null ? uri : file.getName(), e.getMessage()), 185 dialogTitle, 186 JOptionPane.ERROR_MESSAGE, 187 null 188 ); 189 cancel(); 190 } 191 } 192}