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