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.gui.HelpAwareOptionPane; 022import org.openstreetmap.josm.gui.NavigatableComponent.ViewportData; 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 Thread.dumpStack(); 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 FileOutputStream out = new FileOutputStream(file); 156 try { 157 Utils.copyStream(is, out); 158 } finally { 159 Utils.close(out); 160 } 161 } 162 reader.loadSession(file, zip, monitor); 163 layers = reader.getLayers(); 164 active = reader.getActive(); 165 postLoadTasks = reader.getPostLoadTasks(); 166 viewport = reader.getViewport(); 167 } finally { 168 if (tempFile) { 169 if (!file.delete()) { 170 file.deleteOnExit(); 171 } 172 file = null; 173 } 174 } 175 } catch (IllegalDataException e) { 176 e.printStackTrace(); 177 HelpAwareOptionPane.showMessageDialogInEDT( 178 Main.parent, 179 tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", uri != null ? uri : file.getName(), e.getMessage()), 180 tr("Data Error"), 181 JOptionPane.ERROR_MESSAGE, 182 null 183 ); 184 cancel(); 185 } catch (IOException e) { 186 e.printStackTrace(); 187 HelpAwareOptionPane.showMessageDialogInEDT( 188 Main.parent, 189 tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", uri != null ? uri : file.getName(), e.getMessage()), 190 tr("IO Error"), 191 JOptionPane.ERROR_MESSAGE, 192 null 193 ); 194 cancel(); 195 } catch (RuntimeException e) { 196 cancel(); 197 throw e; 198 } catch (Error e) { 199 cancel(); 200 throw e; 201 } 202 } 203 } 204} 205