Index: trunk/src/org/openstreetmap/josm/actions/UpdateModifiedAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UpdateModifiedAction.java	(revision 13496)
+++ trunk/src/org/openstreetmap/josm/actions/UpdateModifiedAction.java	(revision 13497)
@@ -11,4 +11,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
+import org.openstreetmap.josm.data.osm.DataSet.DownloadPolicy;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.io.OnlineResource;
@@ -46,5 +47,7 @@
     @Override
     protected void updateEnabledState() {
-        setEnabled(getLayerManager().getEditDataSet() != null && !Main.isOffline(OnlineResource.OSM_API));
+        DataSet ds = getLayerManager().getEditDataSet();
+        setEnabled(ds != null && !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy())
+                && !Main.isOffline(OnlineResource.OSM_API));
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/UploadSelectionAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(revision 13496)
+++ trunk/src/org/openstreetmap/josm/actions/UploadSelectionAction.java	(revision 13497)
@@ -64,4 +64,8 @@
     protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
         updateEnabledStateOnModifiableSelection(selection);
+        OsmDataLayer editLayer = getLayerManager().getEditLayer();
+        if (editLayer != null && !editLayer.isUploadable()) {
+            setEnabled(false);
+        }
     }
 
@@ -89,5 +93,5 @@
     public void actionPerformed(ActionEvent e) {
         OsmDataLayer editLayer = getLayerManager().getEditLayer();
-        if (!isEnabled())
+        if (!isEnabled() || !editLayer.isUploadable())
             return;
         if (editLayer.isUploadDiscouraged() && UploadAction.warnUploadDiscouraged(editLayer)) {
@@ -203,6 +207,5 @@
                 hull.add(w);
                 for (Node n: w.getNodes()) {
-                    // we upload modified nodes even if they aren't in the current
-                    // selection.
+                    // we upload modified nodes even if they aren't in the current selection.
                     n.accept(this);
                 }
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 13496)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 13497)
@@ -329,4 +329,5 @@
             version = copyFrom.version;
             uploadPolicy = copyFrom.uploadPolicy;
+            downloadPolicy = copyFrom.downloadPolicy;
             isReadOnly.set(copyFrom.isReadOnly.get());
         } finally {
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(revision 13496)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSetMerger.java	(revision 13497)
@@ -4,4 +4,5 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
+import java.awt.geom.Area;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -14,4 +15,5 @@
 import java.util.Set;
 
+import org.openstreetmap.josm.data.DataSource;
 import org.openstreetmap.josm.data.conflict.Conflict;
 import org.openstreetmap.josm.data.conflict.ConflictCollection;
@@ -432,4 +434,32 @@
             candidates.clear();
             fixReferences();
+
+            Area a = targetDataSet.getDataSourceArea();
+
+            // copy the merged layer's data source info.
+            // only add source rectangles if they are not contained in the layer already.
+            for (DataSource src : sourceDataSet.getDataSources()) {
+                if (a == null || !a.contains(src.bounds.asRect())) {
+                    targetDataSet.addDataSource(src);
+                }
+            }
+
+            // copy the merged layer's API version
+            if (targetDataSet.getVersion() == null) {
+                targetDataSet.setVersion(sourceDataSet.getVersion());
+            }
+
+            // copy the merged layer's policies and locked status
+            if (sourceDataSet.getUploadPolicy() != null && (targetDataSet.getUploadPolicy() == null
+                    || sourceDataSet.getUploadPolicy().compareTo(targetDataSet.getUploadPolicy()) > 0)) {
+                targetDataSet.setUploadPolicy(sourceDataSet.getUploadPolicy());
+            }
+            if (sourceDataSet.getDownloadPolicy() != null && (targetDataSet.getDownloadPolicy() == null
+                    || sourceDataSet.getDownloadPolicy().compareTo(targetDataSet.getDownloadPolicy()) > 0)) {
+                targetDataSet.setDownloadPolicy(sourceDataSet.getDownloadPolicy());
+            }
+            if (sourceDataSet.isLocked() && !targetDataSet.isLocked()) {
+                targetDataSet.lock();
+            }
         } finally {
             targetDataSet.endUpdate();
Index: trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 13496)
+++ trunk/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java	(revision 13497)
@@ -552,19 +552,4 @@
         }
 
-        Area a = data.getDataSourceArea();
-
-        // copy the merged layer's data source info.
-        // only add source rectangles if they are not contained in the layer already.
-        for (DataSource src : from.getDataSources()) {
-            if (a == null || !a.contains(src.bounds.asRect())) {
-                data.addDataSource(src);
-            }
-        }
-
-        // copy the merged layer's API version
-        if (data.getVersion() == null) {
-            data.setVersion(from.getVersion());
-        }
-
         int numNewConflicts = 0;
         for (Conflict<?> c : visitor.getConflicts()) {
Index: trunk/test/unit/org/openstreetmap/josm/data/osm/DataSetTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/osm/DataSetTest.java	(revision 13496)
+++ trunk/test/unit/org/openstreetmap/josm/data/osm/DataSetTest.java	(revision 13497)
@@ -3,4 +3,5 @@
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -14,4 +15,5 @@
 import org.junit.Test;
 import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.DataSet.DownloadPolicy;
 import org.openstreetmap.josm.data.osm.DataSet.UploadPolicy;
 import org.openstreetmap.josm.testutils.JOSMTestRules;
@@ -194,4 +196,39 @@
     }
 
+    /**
+     * Unit test for {@link DataSet#mergeFrom} - Policies.
+     */
+    @Test
+    public void testMergePolicies() {
+        DataSet ds1 = new DataSet();
+        DataSet ds2 = new DataSet();
+
+        ds1.setUploadPolicy(UploadPolicy.BLOCKED);
+        ds2.setUploadPolicy(UploadPolicy.NORMAL);
+        ds1.mergeFrom(ds2);
+        assertEquals(UploadPolicy.BLOCKED, ds1.getUploadPolicy());
+
+        ds1.setUploadPolicy(UploadPolicy.NORMAL);
+        ds2.setUploadPolicy(UploadPolicy.BLOCKED);
+        ds1.mergeFrom(ds2);
+        assertEquals(UploadPolicy.BLOCKED, ds1.getUploadPolicy());
+
+        ds1.setDownloadPolicy(DownloadPolicy.BLOCKED);
+        ds2.setDownloadPolicy(DownloadPolicy.NORMAL);
+        ds1.mergeFrom(ds2);
+        assertEquals(DownloadPolicy.BLOCKED, ds1.getDownloadPolicy());
+
+        ds1.setDownloadPolicy(DownloadPolicy.NORMAL);
+        ds2.setDownloadPolicy(DownloadPolicy.BLOCKED);
+        ds1.mergeFrom(ds2);
+        assertEquals(DownloadPolicy.BLOCKED, ds1.getDownloadPolicy());
+
+        ds2.lock();
+        assertFalse(ds1.isLocked());
+        assertTrue(ds2.isLocked());
+        ds1.mergeFrom(ds2);
+        assertTrue(ds1.isLocked());
+    }
+
     private static void assertEqualsDataSet(DataSet ds1, DataSet ds2) {
         assertEquals(new ArrayList<>(ds1.getNodes()), new ArrayList<>(ds2.getNodes()));
@@ -202,3 +239,14 @@
         assertEquals(ds1.getVersion(), ds2.getVersion());
     }
+
+    /**
+     * Checks that enum values are defined in the correct order.
+     */
+    @Test
+    public void testEnumOrder() {
+        assertTrue(DownloadPolicy.BLOCKED.compareTo(DownloadPolicy.NORMAL) > 0);
+        assertTrue(UploadPolicy.BLOCKED.compareTo(UploadPolicy.NORMAL) > 0);
+        assertTrue(UploadPolicy.BLOCKED.compareTo(UploadPolicy.DISCOURAGED) > 0);
+        assertTrue(UploadPolicy.DISCOURAGED.compareTo(UploadPolicy.NORMAL) > 0);
+    }
 }
