Index: trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 6244)
+++ trunk/src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 6245)
@@ -53,5 +53,6 @@
                 "org.openstreetmap.josm.io.JpgImporter",
                 "org.openstreetmap.josm.io.WMSLayerImporter",
-                "org.openstreetmap.josm.io.AllFormatsImporter"
+                "org.openstreetmap.josm.io.AllFormatsImporter",
+                "org.openstreetmap.josm.io.session.SessionImporter"
         };
 
Index: trunk/src/org/openstreetmap/josm/actions/OpenLocationAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/OpenLocationAction.java	(revision 6244)
+++ trunk/src/org/openstreetmap/josm/actions/OpenLocationAction.java	(revision 6245)
@@ -28,4 +28,5 @@
 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmUrlTask;
+import org.openstreetmap.josm.actions.downloadtasks.DownloadSessionTask;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
 import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
@@ -62,4 +63,5 @@
         addDownloadTaskClass(DownloadOsmCompressedTask.class);
         addDownloadTaskClass(DownloadOsmChangeCompressedTask.class);
+        addDownloadTaskClass(DownloadSessionTask.class);
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java	(revision 6244)
+++ trunk/src/org/openstreetmap/josm/actions/SessionLoadAction.java	(revision 6245)
@@ -7,5 +7,8 @@
 import java.awt.event.ActionEvent;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
 import java.util.Arrays;
 import java.util.List;
@@ -23,8 +26,18 @@
 import org.openstreetmap.josm.gui.util.FileFilterAllFiles;
 import org.openstreetmap.josm.io.IllegalDataException;
+import org.openstreetmap.josm.io.session.SessionImporter;
 import org.openstreetmap.josm.io.session.SessionReader;
-
+import org.openstreetmap.josm.tools.CheckParameterUtil;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Loads a JOSM session
+ * @since 4668
+ */
 public class SessionLoadAction extends DiskAccessAction {
 
+    /**
+     * Constructs a new {@code SessionLoadAction}.
+     */
     public SessionLoadAction() {
         super(tr("Load Session"), "open", tr("Load a session from file."), null, true, "load-session", true);
@@ -34,6 +47,7 @@
     @Override
     public void actionPerformed(ActionEvent e) {
-        ExtensionFileFilter ff = new ExtensionFileFilter("jos,joz", "jos", tr("Session file (*.jos, *.joz)"));
-        JFileChooser fc = createAndOpenFileChooser(true, false, tr("Open session"), Arrays.asList(ff, FileFilterAllFiles.getInstance()), ff, JFileChooser.FILES_ONLY, "lastDirectory");
+        JFileChooser fc = createAndOpenFileChooser(true, false, tr("Open session"), 
+                Arrays.asList(SessionImporter.FILE_FILTER, FileFilterAllFiles.getInstance()), 
+                SessionImporter.FILE_FILTER, JFileChooser.FILES_ONLY, "lastDirectory");
         if (fc == null) return;
         File file = fc.getSelectedFile();
@@ -42,21 +56,51 @@
     }
 
+    /**
+     * JOSM session loader
+     */
     public static class Loader extends PleaseWaitRunnable {
 
         private boolean canceled;
         private File file;
-        private boolean zip;
+        private final URI uri;
+        private final InputStream is;
+        private final boolean zip;
         private List<Layer> layers;
         private List<Runnable> postLoadTasks;
         private ViewportData viewport;
 
+        /**
+         * Constructs a new {@code Loader} for local session file.
+         * @param file The JOSM session file
+         * @param zip {@code true} if the file is a session archive file (*.joz)
+         */
         public Loader(File file, boolean zip) {
             super(tr("Loading session ''{0}''", file.getName()));
+            CheckParameterUtil.ensureParameterNotNull(file, "file");
             this.file = file;
+            this.uri = null;
+            this.is = null;
             this.zip = zip;
         }
 
+        /**
+         * Constructs a new {@code Loader} for session file input stream (may be a remote file).
+         * @param is The input stream to session file
+         * @param uri The file URI
+         * @param zip {@code true} if the file is a session archive file (*.joz)
+         * @since 6245
+         */
+        public Loader(InputStream is, URI uri, boolean zip) {
+            super(tr("Loading session ''{0}''", uri));
+            CheckParameterUtil.ensureParameterNotNull(is, "is");
+            CheckParameterUtil.ensureParameterNotNull(uri, "uri");
+            this.file = null;
+            this.uri = uri;
+            this.is = is;
+            this.zip = zip;
+        }
+
         @Override
-        protected void cancel() {
+        public void cancel() {
             Thread.dumpStack();
             canceled = true;
@@ -99,13 +143,34 @@
                 ProgressMonitor monitor = getProgressMonitor();
                 SessionReader reader = new SessionReader();
-                reader.loadSession(file, zip, monitor);
-                layers = reader.getLayers();
-                postLoadTasks = reader.getPostLoadTasks();
-                viewport = reader.getViewport();
+                boolean tempFile = false;
+                try {
+                    if (file == null) {
+                        // Download and write entire joz file as a temp file on disk as we need random access later
+                        file = File.createTempFile("session_", ".joz", Utils.getJosmTempDir());
+                        tempFile = true;
+                        FileOutputStream out = new FileOutputStream(file);
+                        try {
+                            Utils.copyStream(is, out);
+                        } finally {
+                            Utils.close(out);
+                        }
+                    }
+                    reader.loadSession(file, zip, monitor);
+                    layers = reader.getLayers();
+                    postLoadTasks = reader.getPostLoadTasks();
+                    viewport = reader.getViewport();
+                } finally {
+                    if (tempFile) {
+                        if (!file.delete()) {
+                            file.deleteOnExit();
+                        }
+                        file = null;
+                    }
+                }
             } catch (IllegalDataException e) {
                 e.printStackTrace();
                 HelpAwareOptionPane.showMessageDialogInEDT(
                         Main.parent,
-                        tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", file.getName(), e.getMessage()),
+                        tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", uri != null ? uri : file.getName(), e.getMessage()),
                         tr("Data Error"),
                         JOptionPane.ERROR_MESSAGE,
@@ -117,5 +182,5 @@
                 HelpAwareOptionPane.showMessageDialogInEDT(
                         Main.parent,
-                        tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", file.getName(), e.getMessage()),
+                        tr("<html>Could not load session file ''{0}''.<br>Error is:<br>{1}</html>", uri != null ? uri : file.getName(), e.getMessage()),
                         tr("IO Error"),
                         JOptionPane.ERROR_MESSAGE,
Index: trunk/src/org/openstreetmap/josm/actions/SessionSaveAsAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/SessionSaveAsAction.java	(revision 6244)
+++ trunk/src/org/openstreetmap/josm/actions/SessionSaveAsAction.java	(revision 6245)
@@ -42,4 +42,8 @@
 import org.openstreetmap.josm.tools.WindowGeometry;
 
+/**
+ * Saves a JOSM session
+ * @since 4685
+ */
 public class SessionSaveAsAction extends DiskAccessAction {
 
@@ -50,4 +54,7 @@
     private boolean zipRequired;
 
+    /**
+     * Constructs a new {@code SessionSaveAsAction}.
+     */
     public SessionSaveAsAction() {
         super(tr("Save Session As..."), "save_as", tr("Save the current session to a new file."), null, true, "save_as-session", true);
@@ -134,6 +141,12 @@
     }
 
+    /**
+     * The "Save Session" dialog
+     */
     public class SessionSaveAsDialog extends ExtendedDialog {
 
+        /**
+         * Constructs a new {@code SessionSaveAsDialog}.
+         */
         public SessionSaveAsDialog() {
             super(Main.parent, tr("Save Session"), new String[] {tr("Save As"), tr("Cancel")});
@@ -229,4 +242,3 @@
         setEnabled(Main.isDisplayingMapView());
     }
-
 }
Index: trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadSessionTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadSessionTask.java	(revision 6245)
+++ trunk/src/org/openstreetmap/josm/actions/downloadtasks/DownloadSessionTask.java	(revision 6245)
@@ -0,0 +1,79 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions.downloadtasks;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.concurrent.Future;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.SessionLoadAction.Loader;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.tools.Utils;
+
+/**
+ * Task allowing to download JOSM session (*.jos, *.joz file).
+ * @since 6215
+ */
+public class DownloadSessionTask extends AbstractDownloadTask {
+
+    private static final String PATTERN_SESSION =  "https?://.*/.*\\.jo(s|z)";
+    
+    private Loader loader;
+    
+    /**
+     * Constructs a new {@code DownloadSessionTask}.
+     */
+    public DownloadSessionTask() {
+    }
+
+    @Override
+    public String getTitle() {
+        return tr("Download session");
+    }
+
+    @Override
+    public String[] getPatterns() {
+        return new String[]{PATTERN_SESSION};
+    }
+
+    @Override
+    public Future<?> download(boolean newLayer, Bounds downloadArea, ProgressMonitor progressMonitor) {
+        return null;
+    }
+
+    @Override
+    public Future<?> loadUrl(boolean newLayer, String url, ProgressMonitor progressMonitor) {
+        if (url != null && (url.matches(PATTERN_SESSION))) {
+            try {
+                URL u = new URL(url);
+                loader = new Loader(Utils.openURL(u), u.toURI(), url.endsWith(".joz"));
+                return Main.worker.submit(loader);
+            } catch (URISyntaxException e) {
+                e.printStackTrace();
+            } catch (MalformedURLException e) {
+                e.printStackTrace();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void cancel() {
+        if (loader != null) {
+            loader.cancel();
+        }
+    }
+
+    @Override
+    public String getConfirmationMessage(URL url) {
+        // TODO
+        return null;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/session/SessionImporter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionImporter.java	(revision 6245)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionImporter.java	(revision 6245)
@@ -0,0 +1,40 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io.session;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.actions.SessionLoadAction.Loader;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.FileImporter;
+import org.openstreetmap.josm.io.IllegalDataException;
+
+/**
+ * File importer allowing to import session files (*.jos/joz files).
+ * @since 6245
+ */
+public class SessionImporter extends FileImporter {
+
+    /**
+     * The file filter used to load JOSM session files
+     */
+    public static final ExtensionFileFilter FILE_FILTER = new ExtensionFileFilter(
+            "jos,joz", "jos", tr("Session file (*.jos, *.joz)"));
+
+    /**
+     * Constructs a new {@code SessionImporter}.
+     */
+    public SessionImporter() {
+        super(FILE_FILTER);
+    }
+
+    @Override
+    public void importData(File file, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
+        boolean zip = file.getName().toLowerCase().endsWith(".joz");
+        Main.worker.submit(new Loader(file, zip));
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/session/SessionReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 6244)
+++ trunk/src/org/openstreetmap/josm/io/session/SessionReader.java	(revision 6245)
@@ -85,6 +85,6 @@
     }
 
-    private File sessionFile;
-    private boolean zip; /* true, if session file is a .joz file; false if it is a .jos file */
+    private URI sessionFileURI;
+    private boolean zip; // true, if session file is a .joz file; false if it is a .jos file
     private ZipFile zipFile;
     private List<Layer> layers = new ArrayList<Layer>();
@@ -208,5 +208,5 @@
                                 // relative to session file - "../" step out of the archive
                                 String relPath = uri.getPath().substring(3);
-                                return new File(sessionFile.toURI().resolve(relPath));
+                                return new File(sessionFileURI.resolve(relPath));
                             } else {
                                 // file inside zip archive
@@ -215,5 +215,5 @@
                             }
                         } else
-                            return new File(sessionFile.toURI().resolve(uri));
+                            return new File(sessionFileURI.resolve(uri));
                     }
                 } else
@@ -225,5 +225,6 @@
 
         /**
-         * Returns true if we are reading from a .joz file.
+         * Determines if we are reading from a .joz file.
+         * @return {@code true} if we are reading from a .joz file, {@code false} otherwise
          */
         public boolean isZip() {
@@ -278,5 +279,5 @@
     }
 
-    private void error(String msg) throws IllegalDataException {
+    private static void error(String msg) throws IllegalDataException {
         throw new IllegalDataException(msg);
     }
@@ -530,6 +531,4 @@
             progressMonitor = NullProgressMonitor.INSTANCE;
         }
-        this.sessionFile = sessionFile;
-        this.zip = zip;
 
         InputStream josIS = null;
@@ -538,17 +537,5 @@
             try {
                 zipFile = new ZipFile(sessionFile);
-                ZipEntry josEntry = null;
-                Enumeration<? extends ZipEntry> entries = zipFile.entries();
-                while (entries.hasMoreElements()) {
-                    ZipEntry entry = entries.nextElement();
-                    if (entry.getName().toLowerCase().endsWith(".jos")) {
-                        josEntry = entry;
-                        break;
-                    }
-                }
-                if (josEntry == null) {
-                    error(tr("expected .jos file inside .joz archive"));
-                }
-                josIS = zipFile.getInputStream(josEntry);
+                josIS = getZipInputStream(zipFile);
             } catch (ZipException ze) {
                 throw new IOException(ze);
@@ -562,4 +549,28 @@
         }
 
+        loadSession(josIS, sessionFile.toURI(), zip, progressMonitor);
+    }
+
+    private static InputStream getZipInputStream(ZipFile zipFile) throws ZipException, IOException, IllegalDataException {
+        ZipEntry josEntry = null;
+        Enumeration<? extends ZipEntry> entries = zipFile.entries();
+        while (entries.hasMoreElements()) {
+            ZipEntry entry = entries.nextElement();
+            if (entry.getName().toLowerCase().endsWith(".jos")) {
+                josEntry = entry;
+                break;
+            }
+        }
+        if (josEntry == null) {
+            error(tr("expected .jos file inside .joz archive"));
+        }
+        return zipFile.getInputStream(josEntry);
+    }
+
+    private void loadSession(InputStream josIS, URI sessionFileURI, boolean zip, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
+        
+        this.sessionFileURI = sessionFileURI;
+        this.zip = zip;
+        
         try {
             DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
@@ -581,4 +592,3 @@
         return (Element) els.item(0);
     }
-
 }
Index: trunk/src/org/openstreetmap/josm/tools/Utils.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 6244)
+++ trunk/src/org/openstreetmap/josm/tools/Utils.java	(revision 6245)
@@ -728,3 +728,22 @@
         return all.toString();
     }
+
+    /**
+     * Returns the JOSM temp directory.
+     * @return The JOSM temp directory ({@code <java.io.tmpdir>/JOSM}), or {@code null} if {@code java.io.tmpdir} is not defined
+     * @since 6245
+     */
+    public static File getJosmTempDir() {
+        String tmpDir = System.getProperty("java.io.tmpdir");
+        if (tmpDir == null) {
+            return null;
+        }
+        File josmTmpDir = new File(tmpDir, "JOSM");
+        if (!josmTmpDir.exists()) {
+            if (!josmTmpDir.mkdirs()) {
+                Main.warn("Unable to create temp directory "+josmTmpDir);
+            }
+        }
+        return josmTmpDir;
+    }
 }
