Index: trunk/src/org/openstreetmap/josm/actions/DuplicateLayerAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/DuplicateLayerAction.java	(revision 2901)
+++ trunk/src/org/openstreetmap/josm/actions/DuplicateLayerAction.java	(revision 2901)
@@ -0,0 +1,58 @@
+// License: GPL. See LICENSE file for details.
+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.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.gui.layer.OsmDataLayer;
+import org.openstreetmap.josm.tools.Shortcut;
+
+public class DuplicateLayerAction extends JosmAction {
+
+    public DuplicateLayerAction() {
+        super(tr("Duplicate Layer"), "dialogs/duplicatelayer", tr("Make a duplicate of the currently selected layer."),
+                Shortcut.registerShortcut("layer:duplicate", tr("Layer: {0}", tr("Duplicate")), KeyEvent.VK_N, Shortcut.GROUP_NONE), true);
+        putValue("help", ht("/Action/DuplicateLayer"));
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        Layer sourceLayer = Main.main.getEditLayer();
+        if (sourceLayer == null)
+            return;
+        duplicate(sourceLayer);
+    }
+
+    public void duplicate(Layer layer) {
+        if ((Main.map == null) || (Main.map.mapView == null))
+            return;
+        List<String> layerNames = new ArrayList<String>();
+        for (Layer l: Main.map.mapView.getAllLayers()) {
+            layerNames.add(l.getName());
+        }
+        if (layer instanceof OsmDataLayer) {
+            OsmDataLayer oldLayer = (OsmDataLayer)layer;
+            // Translators: "Copy of {layer name}"
+            String newName = tr("Copy of {0}", oldLayer.getName());
+            int i = 2;
+            while (layerNames.contains(newName)) {
+                // Translators: "Copy {number} of {layer name}"
+                newName = tr("Copy {1} of {0}", oldLayer.getName(), i);
+                i++;
+            }
+            Main.main.addLayer(new OsmDataLayer(oldLayer.data.clone(), newName, null));
+        }
+    }
+
+    public static boolean canDuplicate(Layer layer) {
+        if (layer instanceof OsmDataLayer)
+            return true;
+        return false;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 2900)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/LayerListDialog.java	(revision 2901)
@@ -38,4 +38,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.DuplicateLayerAction;
 import org.openstreetmap.josm.actions.MergeLayerAction;
 import org.openstreetmap.josm.gui.MapFrame;
@@ -130,4 +131,10 @@
         buttonPanel.add(new SideButton(mergeLayerAction));
 
+        // -- duplicate layer action
+        DuplicateAction duplicateLayerAction = new DuplicateAction();
+        adaptTo(duplicateLayerAction, model);
+        adaptTo(duplicateLayerAction, selectionModel);
+        buttonPanel.add(new SideButton(duplicateLayerAction));
+
         //-- delete layer action
         DeleteLayerAction deleteLayerAction = new DeleteLayerAction();
@@ -480,4 +487,53 @@
 
     /**
+     * The action to merge the currently selected layer into another layer.
+     */
+    public final class DuplicateAction extends AbstractAction implements IEnabledStateUpdating {
+        private  Layer layer;
+
+        public DuplicateAction(Layer layer) throws IllegalArgumentException {
+            this();
+            CheckParameterUtil.ensureParameterNotNull(layer, "layer");
+            this.layer = layer;
+            putValue(NAME, tr("Duplicate"));
+            updateEnabledState();
+        }
+
+        public DuplicateAction() {
+            putValue(SMALL_ICON, ImageProvider.get("dialogs", "duplicatelayer"));
+            putValue(SHORT_DESCRIPTION, tr("Duplicate this layer"));
+            putValue("help", HelpUtil.ht("/Dialog/LayerDialog#DuplicateLayer"));
+            updateEnabledState();
+        }
+
+        public void actionPerformed(ActionEvent e) {
+            if (layer != null) {
+                new DuplicateLayerAction().duplicate(layer);
+            } else {
+                Layer selectedLayer = getModel().getSelectedLayers().get(0);
+                new DuplicateLayerAction().duplicate(selectedLayer);
+            }
+        }
+
+        protected boolean isActiveLayer(Layer layer) {
+            if (Main.map == null) return false;
+            if (Main.map.mapView == null) return false;
+            return Main.map.mapView.getActiveLayer() == layer;
+        }
+
+        public void updateEnabledState() {
+            if (layer == null) {
+                if (getModel().getSelectedLayers().size() == 1) {
+                    setEnabled(DuplicateLayerAction.canDuplicate(getModel().getSelectedLayers().get(0)));
+                } else {
+                    setEnabled(false);
+                }
+            } else {
+                setEnabled(DuplicateLayerAction.canDuplicate(layer));
+            }
+        }
+    }
+
+    /**
      * the list cell renderer used to render layer list entries
      *
