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