Index: trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java	(revision 8603)
+++ trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java	(revision 8604)
@@ -199,4 +199,7 @@
      */
     protected boolean isObjectLoadable() {
+        if (cacheData == null) {
+            return false;
+        }
         byte[] content = cacheData.getContent();
         return content != null && content.length > 0;
@@ -338,5 +341,10 @@
 
                 attributes.setResponseCode(urlConn.getResponseCode());
-                byte[] raw = Utils.readBytesFromStream(urlConn.getInputStream());
+                byte[] raw;
+                if (urlConn.getResponseCode() == 200) {
+                    raw = Utils.readBytesFromStream(urlConn.getInputStream());
+                } else {
+                    raw = new byte[]{};
+                }
 
                 if (isResponseLoadable(urlConn.getHeaderFields(), urlConn.getResponseCode(), raw)) {
@@ -440,6 +448,8 @@
         urlConn.setReadTimeout(readTimeout); // 30 seconds read timeout
         urlConn.setConnectTimeout(connectTimeout);
-        for (Map.Entry<String, String> e: headers.entrySet()) {
-            urlConn.setRequestProperty(e.getKey(), e.getValue());
+        if (headers != null) {
+            for (Map.Entry<String, String> e: headers.entrySet()) {
+                urlConn.setRequestProperty(e.getKey(), e.getValue());
+            }
         }
         if (force) {
Index: trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java	(revision 8603)
+++ trunk/src/org/openstreetmap/josm/data/imagery/WMTSTileSource.java	(revision 8604)
@@ -142,5 +142,5 @@
         }
 
-        private static final String[] getLayerNames(Collection<Layer> layers) {
+        private static String[] getLayerNames(Collection<Layer> layers) {
             Collection<String> ret = new ArrayList<>();
             for (Layer layer: layers) {
Index: trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 8603)
+++ trunk/src/org/openstreetmap/josm/gui/layer/AbstractTileSourceLayer.java	(revision 8604)
@@ -186,5 +186,4 @@
         }
 
-
         if (tileLoader == null)
             tileLoader = new OsmTileLoader(this);
Index: trunk/src/org/openstreetmap/josm/gui/preferences/imagery/CacheContentsPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/imagery/CacheContentsPanel.java	(revision 8603)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/imagery/CacheContentsPanel.java	(revision 8604)
@@ -55,5 +55,5 @@
 public class CacheContentsPanel extends JPanel {
 
-    private static class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener {
+    private static final class ButtonColumn extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener {
         private final Action action;
         private final JButton renderButton;
Index: trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java	(revision 8604)
+++ trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java	(revision 8604)
@@ -0,0 +1,101 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.cache;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.jcs.access.behavior.ICacheAccess;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openstreetmap.josm.JOSMFixture;
+
+public class JCSCachedTileLoaderJobTest {
+    private static class TestCachedTileLoaderJob extends JCSCachedTileLoaderJob<String, CacheEntry> {
+
+        private int responseCode;
+
+        public TestCachedTileLoaderJob(int responseCode) throws IOException {
+            super(getCache(), 30000, 30000, null);
+            this.responseCode = responseCode;
+        }
+
+        private static ICacheAccess<String, CacheEntry> getCache() throws IOException {
+         return JCSCacheManager.getCache("test");
+        }
+
+        @Override
+        public String getCacheKey() {
+            return "cachekey";
+        }
+
+        @Override
+        public URL getUrl() {
+            try {
+                return new URL("http://httpstat.us/" + Integer.toString(responseCode));
+            } catch (MalformedURLException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        @Override
+        protected CacheEntry createCacheEntry(byte[] content) {
+            return new CacheEntry("dummy".getBytes());
+        }
+
+    }
+
+    private static class Listener implements ICachedLoaderListener {
+        private CacheEntry data;
+        private CacheEntryAttributes attributes;
+        private LoadResult result;
+        private boolean ready;
+
+        @Override
+        public synchronized void loadingFinished(CacheEntry data, CacheEntryAttributes attributes, LoadResult result) {
+            this.data = data;
+            this.attributes = attributes;
+            this.result = result;
+            this.ready = true;
+            this.notify();
+        }
+
+    }
+    /**
+     * Setup test.
+     */
+    @BeforeClass
+    public static void setUp() {
+        JOSMFixture.createUnitTestFixture().init();
+    }
+
+    @Test
+    public void testStatusCodes() throws Exception {
+        testStatusCode(200);
+        // can't test for 3xx, as httpstat.us redirects finally to 200 page
+        testStatusCode(401);
+        testStatusCode(402);
+        testStatusCode(403);
+        testStatusCode(404);
+        testStatusCode(405);
+        testStatusCode(500);
+        testStatusCode(501);
+        testStatusCode(502);
+    }
+
+    public void testStatusCode(int responseCode) throws Exception {
+        TestCachedTileLoaderJob job = new TestCachedTileLoaderJob(responseCode);
+        Listener listener = new Listener();
+        job.submit(listener, true);
+        synchronized (listener) {
+            if (!listener.ready) {
+                listener.wait();
+            }
+        }
+        assertEquals(responseCode, listener.attributes.getResponseCode());
+
+    }
+}
+
