### Eclipse Workspace Patch 1.0
#P core
Index: src/org/openstreetmap/josm/actions/SaveSessionAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/SaveSessionAction.java	(revision 0)
+++ src/org/openstreetmap/josm/actions/SaveSessionAction.java	(revision 0)
@@ -0,0 +1,48 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.io.File;
+
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.io.SessionExporter;
+
+public class SaveSessionAction extends SaveActionBase {
+
+    public SaveSessionAction() {
+        super(tr("Save Session"), "savesession", tr("Save the current session."),
+                null);
+        putValue("help", ht("/Action/Save"));
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+        doSave();
+
+    }
+
+    @Override
+    public boolean doSave() {
+        File file = createAndOpenSaveFileChooser(tr("Save Session file"), "jos");
+
+
+        SessionExporter exporter = new SessionExporter();
+
+        exporter.exportData(file);
+
+        return true;
+
+
+
+    }
+
+    @Override
+    protected File getFile(Layer layer) {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+}
Index: src/org/openstreetmap/josm/io/AllFormatsImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/AllFormatsImporter.java	(revision 3616)
+++ src/org/openstreetmap/josm/io/AllFormatsImporter.java	(working copy)
@@ -12,8 +12,8 @@
  */
 public class AllFormatsImporter extends FileImporter {
     public AllFormatsImporter() {
-        super(new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz,gpx,gpx.gz,nmea,nme,nma,log,txt,wms,jpg", "", tr("All Formats")
-                    + " (*.gpx *.osm *.nmea *.jpg ...)"));
+        super(new ExtensionFileFilter("osm,xml,osm.gz,osm.bz2,osm.bz,gpx,gpx.gz,nmea,nme,nma,log,txt,wms,jpg,jos", "", tr("All Formats")
+                + " (*.gpx *.osm *.nmea *.jpg ...)"));
     }
     @Override public boolean acceptFile(File pathname) {
         return false;
Index: src/org/openstreetmap/josm/io/FileImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/FileImporter.java	(revision 3616)
+++ src/org/openstreetmap/josm/io/FileImporter.java	(working copy)
@@ -12,11 +12,13 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.ExtensionFileFilter;
 import org.openstreetmap.josm.gui.HelpAwareOptionPane;
+import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 
 public abstract class FileImporter implements Comparable<FileImporter> {
 
     public final ExtensionFileFilter filter;
+    protected Layer layer;
 
     public FileImporter(ExtensionFileFilter filter) {
         this.filter = filter;
@@ -94,4 +96,12 @@
         return (new Double(this.getPriority())).compareTo(other.getPriority());
     }
 
+    /*
+     * Returns the created layer
+     */
+    public Layer getLayer() {
+        // TODO Auto-generated method stub
+        return layer;
+    }
+
 }
Index: src/org/openstreetmap/josm/io/GpxImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/GpxImporter.java	(revision 3616)
+++ src/org/openstreetmap/josm/io/GpxImporter.java	(working copy)
@@ -40,6 +40,7 @@
             final boolean parsedProperly = r.parse(true);
             r.data.storageFile = file;
             final GpxLayer gpxLayer = new GpxLayer(r.data, fn, true);
+            this.layer=gpxLayer;
 
             // FIXME: remove UI stuff from the IO subsystem
             //
Index: src/org/openstreetmap/josm/io/OsmImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/OsmImporter.java	(revision 3616)
+++ src/org/openstreetmap/josm/io/OsmImporter.java	(working copy)
@@ -14,6 +14,7 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.ExtensionFileFilter;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.gui.layer.Layer;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
@@ -41,6 +42,7 @@
     protected void importData(InputStream in, File associatedFile) throws IllegalDataException {
         DataSet dataSet = OsmReader.parseDataSet(in, NullProgressMonitor.INSTANCE);
         final OsmDataLayer layer = new OsmDataLayer(dataSet, associatedFile.getName(), associatedFile);
+        this.layer=layer;
         // FIXME: remove UI stuff from IO subsystem
         //
         Runnable uiStuff = new Runnable() {
@@ -55,4 +57,10 @@
             SwingUtilities.invokeLater(uiStuff);
         }
     }
+
+
+    @Override
+    public Layer getLayer() {
+        return layer;
+    }
 }
Index: src/org/openstreetmap/josm/io/SessionWriter.java
===================================================================
--- src/org/openstreetmap/josm/io/SessionWriter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/SessionWriter.java	(revision 0)
@@ -0,0 +1,127 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import java.io.PrintWriter;
+import java.util.Collection;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.ProjectionBounds;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
+import org.openstreetmap.josm.gui.layer.geoimage.ImageEntry;
+
+public class SessionWriter extends XmlWriter {
+
+    public SessionWriter(PrintWriter out) {
+        super(out);
+        // TODO Auto-generated constructor stub
+    }
+
+    public void header() {
+        out.println("<?xml version='1.0' encoding='UTF-8'?>");
+        out.print("<josmsession");
+        out.println(" generator='JOSM'>");
+    }
+
+    public void writeView() {
+
+        // What is the center?
+        ProjectionBounds box = Main.map.mapView.getProjectionBounds();
+
+        out.print("<view");
+        out.print(" minEast='");
+        out.print(box.min.east());
+        out.print("'");
+        out.print(" minNorth='");
+        out.print(box.min.north());
+        out.print("'");
+        out.print(" maxEast='");
+        out.print(box.max.east());
+        out.print("'");
+        out.print(" maxNorth='");
+        out.print(box.max.north());
+        out.print("'");
+        out.println(" />");
+    }
+
+    public void writeLayers() {
+        // Do we have layers?
+        Collection<Layer> layers = null;
+        layers = Main.map.mapView.getAllLayers();
+
+        for (Layer layer: layers)
+        {
+            if (layer instanceof OsmDataLayer) {
+                writeOsmLayer(layer);
+            }
+            if (layer instanceof GpxLayer) {
+                writeGpxLayer(layer);
+            }
+            if (layer instanceof GeoImageLayer) {
+                writeGeoImageLayer(layer);
+            }
+        }
+
+    }
+
+    private void writeGeoImageLayer(Layer layer) {
+        GeoImageLayer geoImageLayer = (GeoImageLayer) layer;
+        out.print("<geoimagelayer gpxlayer='");
+        out.print(geoImageLayer.getGpxLayer().getAssociatedFile().getAbsolutePath());
+        out.print("' visible='");
+        if (layer.isVisible()) {
+            out.print("yes");
+        }
+        out.print("'");
+        if (layer == Main.map.mapView.getActiveLayer()) {
+            out.print(" active='yes'");
+        }
+        out.println(">");
+        for (ImageEntry image: geoImageLayer.getImages()) {
+            out.print("<image name='");
+            out.print(image.getFile().getAbsolutePath());
+            out.println("' />");
+        }
+        out.println("</geoimagelayer>");
+    }
+
+    private void writeGenericLayer(String type, Layer layer) {
+        out.print("<");
+        out.print(type);
+        out.print(" name='");
+        out.print(layer.getAssociatedFile().getPath());
+        out.print("'");
+        out.print(" visible='");
+        if (layer.isVisible()) {
+            out.print("yes");
+        }
+        out.print("'");
+        if (layer == Main.map.mapView.getActiveLayer()) {
+            out.print(" active='yes'");
+        }
+        out.println(" />");    }
+
+
+    private void writeGpxLayer(Layer layer) {
+        writeGenericLayer("gpxlayer", layer);
+    }
+
+    private void writeOsmLayer(Layer layer) {
+        writeGenericLayer("osmlayer", layer);
+
+    }
+
+    public void footer() {
+        out.println("</josmsession>");
+    }
+
+    public void close() {
+        out.close();
+    }
+
+
+
+}
+
Index: src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(revision 3616)
+++ src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java	(working copy)
@@ -258,9 +258,9 @@
         }
     }
 
-    public static void create(Collection<File> files, GpxLayer gpxLayer) {
+    public static Layer create(Collection<File> files, GpxLayer gpxLayer) {
         Loader loader = new Loader(files, gpxLayer);
-        Main.worker.execute(loader);
+        return loader.layer;
     }
 
     private GeoImageLayer(final List<ImageEntry> data, GpxLayer gpxLayer) {
@@ -799,4 +799,8 @@
         }
         return copy;
     }
+
+    public Layer getGpxLayer() {
+        return gpxLayer;
+    }
 }
Index: src/org/openstreetmap/josm/io/SessionExporter.java
===================================================================
--- src/org/openstreetmap/josm/io/SessionExporter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/SessionExporter.java	(revision 0)
@@ -0,0 +1,56 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+
+public class SessionExporter extends FileExporter {
+
+    public SessionExporter() {
+        super(new ExtensionFileFilter("jos", "jos", tr("JOSM Session Files") + " (*.jos)"));
+    }
+
+    public void exportData(File file) {
+        try {
+            OutputStream out = getOutputStream(file);
+            Writer writer = new OutputStreamWriter(out, "UTF-8");
+
+            SessionWriter w = new SessionWriter(new PrintWriter(writer));
+
+            w.header();
+            w.writeView();
+            w.writeLayers();
+            w.footer();
+            w.close();
+
+        } catch (IOException e) {
+            e.printStackTrace();
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("<html>An error occurred while saving.<br>Error is:<br>{0}</html>", e.getMessage()),
+                    tr("Error"),
+                    JOptionPane.ERROR_MESSAGE
+            );
+
+        }
+    }
+
+    protected OutputStream getOutputStream(File file) throws FileNotFoundException, IOException {
+        return new FileOutputStream(file);
+    }
+
+}
+
Index: src/org/openstreetmap/josm/io/SessionReader.java
===================================================================
--- src/org/openstreetmap/josm/io/SessionReader.java	(revision 0)
+++ src/org/openstreetmap/josm/io/SessionReader.java	(revision 0)
@@ -0,0 +1,264 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.data.ProjectionBounds;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.gui.layer.GpxLayer;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.tools.CheckParameterUtil;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class SessionReader {
+
+    private class Parser extends DefaultHandler {
+        // Global attributes
+        private Locator locator;
+        private Layer activeLayer;
+        private final List<Layer> layers = new ArrayList<Layer>();
+        private final List<Layer> tmpLayers = new ArrayList<Layer>();
+        private ProjectionBounds box;
+
+        // per-layer attributes
+        private String layerName;
+        private boolean active;
+        private boolean visible;
+        private Collection<File> files = new ArrayList<File>();
+        public String parentLayerName;
+        public String layerType="";
+
+        @Override
+        public void setDocumentLocator(Locator locator) {
+            this.locator = locator;
+        }
+
+        @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
+
+            try {
+                if (qName.equals("view")) {
+                    EastNorth min = new EastNorth(Double.parseDouble(atts.getValue("minEast")), Double.parseDouble(atts.getValue("minNorth")));
+                    EastNorth max = new EastNorth(Double.parseDouble(atts.getValue("maxEast")), Double.parseDouble(atts.getValue("maxNorth")));
+                    this.box = new ProjectionBounds(min, max);
+                } else if (qName.equals("osmlayer") || qName.equals("gpxlayer") || qName.equals("geoimagelayer")) {
+                    newLayerCleanup();
+                    initLayer(qName, atts);
+                } else if (qName.equals("image")) {
+                    String fileName = atts.getValue("name");
+                    File file = new File(fileName);
+                    files.add(file);
+                } else {
+                    System.out.println(tr("Undefined element ''{0}'' found in input stream. Skipping.", qName));
+                }
+            } catch (Exception e) {
+                throw new SAXParseException(e.getMessage(), locator, e);
+            }
+        }
+
+        private void initLayer(String qName, Attributes atts) {
+            String key;
+            layerType = qName;
+            layerName = atts.getValue("name");
+            visible = false;
+            key = atts.getValue("visible");
+            if (key !=null){
+                visible = key.equals("yes");
+            }
+            active = false;
+            key = atts.getValue("active");
+            if (key !=null){
+                active = key.equals("yes");
+            }
+            parentLayerName = atts.getValue("gpxlayer");
+
+        }
+
+        private void newLayerCleanup() {
+            if (layerType.equals("osmlayer")) {
+                loadGenericLayer();
+            }
+            else if (layerType.equals("gpxlayer")) {
+                Layer layer = null;
+                for (Layer existingLayer: tmpLayers) {
+                    if (existingLayer.getAssociatedFile().getAbsolutePath().equals(layerName)) {
+                        layer = existingLayer;
+                        break;
+                    }
+                }
+                if (layer == null) {
+                    // If not found create
+                    loadGenericLayer();
+                } else {
+                    // If already loaded (as part of audio or images) put it in the main list
+                    this.tmpLayers.remove(layer);
+                    this.layers.add(layer);
+                }
+            }
+            else if (layerType.equals("geoimagelayer")) {
+                loadImageLayer();
+            }
+        }
+        private void loadImageLayer() {
+            Layer gpxLayer=null;
+
+
+            // Look for parent layer
+            for (Layer existingLayer: layers) {
+                if (existingLayer.getAssociatedFile().getAbsolutePath().equals(parentLayerName)) {
+                    gpxLayer=existingLayer;
+                    break;
+                }
+            }
+
+            // Load it if not existing
+            if (gpxLayer == null) {
+                gpxLayer=importLayer(parentLayerName);
+                this.tmpLayers.add(gpxLayer);
+            }
+
+            Layer layer = GeoImageLayer.create(files, (GpxLayer)gpxLayer);
+
+
+
+            /*JpgImporter importer = new JpgImporter((GpxLayer)layer);
+            try {
+                importer.importData(files, NullProgressMonitor.INSTANCE);
+            } catch (IOException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            } catch (IllegalDataException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+            layer=importer.getLayer();*/
+            // FIXME : sometimes layer is null
+            if (layer != null) {
+                layer.setVisible(visible);
+            }
+            if (active) {
+                this.activeLayer=layer;
+            }
+            this.layers.add(layer);
+
+
+        }
+
+        private void loadGenericLayer() {
+            Layer layer = importLayer(layerName);
+            this.layers.add(layer);
+        }
+
+        private Layer importLayer(String fileName) {
+            Layer layer = null;
+            File file = new File(fileName);
+            FileImporter importer = null;
+            for (FileImporter imp : ExtensionFileFilter.importers) {
+                if (imp.acceptFile(file)) {
+                    importer=imp;
+                    break;
+                }
+            }
+
+            if (importer != null) {
+                try {
+                    importer.importData(file, NullProgressMonitor.INSTANCE);
+                } catch (IOException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                } catch (IllegalDataException e) {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+                layer=importer.getLayer();
+                layer.setVisible(visible);
+                if (active) {
+                    this.activeLayer=layer;
+                }
+            }
+            return layer;
+        }
+
+        public void manageLayers(){
+            int i=0;
+            for (Layer layer: this.layers) {
+                // FIXME: sometime layer is not yet in main list
+                if (Main.map.mapView.getAllLayersAsList().indexOf(layer)>-1) {
+                    Main.map.mapView.moveLayer(layer, i);
+                }
+                i+=1;
+            }
+
+            if (this.activeLayer != null) {
+                Main.map.mapView.setActiveLayer(activeLayer);
+            }
+        }
+
+        public void manageView() {
+
+            Main.map.mapView.zoomTo(this.box);
+
+        }
+    }
+
+    public static void parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
+        if (progressMonitor == null) {
+            progressMonitor = NullProgressMonitor.INSTANCE;
+        }
+        CheckParameterUtil.ensureParameterNotNull(source, "source");
+        SessionReader reader = new SessionReader();
+        try {
+            progressMonitor.beginTask(tr("Prepare Session data...", 2));
+            progressMonitor.indeterminateSubTask(tr("Parsing Session data..."));
+
+            InputSource inputSource = new InputSource(UTFInputStreamReader.create(source, "UTF-8"));
+            Parser parser = reader.new Parser();
+            SAXParserFactory.newInstance().newSAXParser().parse(inputSource, parser);
+            parser.newLayerCleanup();
+            // FIXME: for some reason we have to wait or we get an exception as some layer not being in the list
+            // when calling Main.map.mapView.moveLayer
+            try {
+                Thread.currentThread();
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+            parser.manageLayers();
+            progressMonitor.worked(1);
+            parser.manageView();
+            progressMonitor.worked(1);
+        } catch(ParserConfigurationException e) {
+            throw new IllegalDataException(e.getMessage(), e);
+        } catch (SAXParseException e) {
+            throw new IllegalDataException(tr("Line {0} column {1}: ", e.getLineNumber(), e.getColumnNumber()) + e.getMessage(), e);
+        } catch(SAXException e) {
+            throw new IllegalDataException(e.getMessage(), e);
+        } catch(Exception e) {
+            throw new IllegalDataException(e);
+        } finally {
+            progressMonitor.finishTask();
+        }
+    }
+
+
+}
Index: src/org/openstreetmap/josm/actions/ExtensionFileFilter.java
===================================================================
--- src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(revision 3616)
+++ src/org/openstreetmap/josm/actions/ExtensionFileFilter.java	(working copy)
@@ -44,6 +44,7 @@
                 "org.openstreetmap.josm.io.NMEAImporter",
                 "org.openstreetmap.josm.io.OsmBzip2Importer",
                 "org.openstreetmap.josm.io.JpgImporter",
+                "org.openstreetmap.josm.io.SessionImporter",
                 "org.openstreetmap.josm.io.AllFormatsImporter"
         };
 
Index: src/org/openstreetmap/josm/io/SessionImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/SessionImporter.java	(revision 0)
+++ src/org/openstreetmap/josm/io/SessionImporter.java	(revision 0)
@@ -0,0 +1,41 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.openstreetmap.josm.actions.ExtensionFileFilter;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+
+public class SessionImporter extends FileImporter {
+
+    public SessionImporter() {
+        super(new ExtensionFileFilter("jos", "jos", tr("OSM Session Files") + " (*.jos)"));
+    }
+
+    public SessionImporter(ExtensionFileFilter filter) {
+        super(filter);
+    }
+
+    @Override public void importData(File file, ProgressMonitor progressMonitor) throws IOException, IllegalDataException {
+        try {
+            FileInputStream in = new FileInputStream(file);
+            importData(in, file);
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+            throw new IOException(tr("File ''{0}'' does not exist.", file.getName()));
+        }
+    }
+
+    protected void importData(InputStream in, File associatedFile) throws IllegalDataException {
+        SessionReader.parseDataSet(in, NullProgressMonitor.INSTANCE);
+    }
+
+}
+
Index: images/savesession.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream

Property changes on: images/savesession.png
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Index: src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainMenu.java	(revision 3616)
+++ src/org/openstreetmap/josm/gui/MainMenu.java	(working copy)
@@ -59,6 +59,7 @@
 import org.openstreetmap.josm.actions.ReverseWayAction;
 import org.openstreetmap.josm.actions.SaveAction;
 import org.openstreetmap.josm.actions.SaveAsAction;
+import org.openstreetmap.josm.actions.SaveSessionAction;
 import org.openstreetmap.josm.actions.SelectAllAction;
 import org.openstreetmap.josm.actions.ShowStatusReportAction;
 import org.openstreetmap.josm.actions.SimplifyWayAction;
@@ -103,6 +104,7 @@
     public final OpenLocationAction openLocation = new OpenLocationAction();
     public final JosmAction save = new SaveAction();
     public final JosmAction saveAs = new SaveAsAction();
+    public final JosmAction saveSession = new SaveSessionAction();
     public final JosmAction gpxExport = new GpxExportAction();
     public final DownloadAction download = new DownloadAction();
     public final DownloadPrimitiveAction downloadPrimitive = new DownloadPrimitiveAction();
@@ -224,6 +226,7 @@
         fileMenu.addSeparator();
         add(fileMenu, save);
         add(fileMenu, saveAs);
+        add(fileMenu, saveSession);
         add(fileMenu, gpxExport);
         fileMenu.addSeparator();
         add(fileMenu, download);
Index: src/org/openstreetmap/josm/io/JpgImporter.java
===================================================================
--- src/org/openstreetmap/josm/io/JpgImporter.java	(revision 3616)
+++ src/org/openstreetmap/josm/io/JpgImporter.java	(working copy)
@@ -47,7 +47,7 @@
             if (files.isEmpty())
                 throw new IOException(tr("No image files found."));
 
-            GeoImageLayer.create(files, gpx);
+            layer = GeoImageLayer.create(files, gpx);
         } finally {
             progressMonitor.finishTask();
         }
