Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 14121)
@@ -11,6 +11,4 @@
 import java.util.Collection;
 import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -36,4 +34,5 @@
 import org.openstreetmap.josm.data.projection.ProjectionRegistry;
 import org.openstreetmap.josm.io.FileWatcher;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -80,8 +79,4 @@
      */
     public static final FileWatcher fileWatcher = new FileWatcher();
-
-    private static final Map<String, Throwable> NETWORK_ERRORS = new HashMap<>();
-
-    private static final Set<OnlineResource> OFFLINE_RESOURCES = EnumSet.noneOf(OnlineResource.class);
 
     /**
@@ -423,15 +418,10 @@
      * @param t The network error
      * @return The previous error associated to the given resource, if any. Can be {@code null}
+     * @deprecated Use {@link NetworkManager#addNetworkError(URL, Throwable)}
      * @since 6642
      */
+    @Deprecated
     public static Throwable addNetworkError(URL url, Throwable t) {
-        if (url != null && t != null) {
-            Throwable old = addNetworkError(url.toExternalForm(), t);
-            if (old != null) {
-                Logging.warn("Already here "+old);
-            }
-            return old;
-        }
-        return null;
+        return NetworkManager.addNetworkError(url, t);
     }
 
@@ -443,11 +433,10 @@
      * @param t The network error
      * @return The previous error associated to the given resource, if any. Can be {@code null}
+     * @deprecated Use {@link NetworkManager#addNetworkError(String, Throwable)}
      * @since 6642
      */
+    @Deprecated
     public static Throwable addNetworkError(String url, Throwable t) {
-        if (url != null && t != null) {
-            return NETWORK_ERRORS.put(url, t);
-        }
-        return null;
+        return NetworkManager.addNetworkError(url, t);
     }
 
@@ -455,16 +444,20 @@
      * Returns the network errors that occured until now.
      * @return the network errors that occured until now, indexed by URL
+     * @deprecated Use {@link NetworkManager#getNetworkErrors}
      * @since 6639
      */
+    @Deprecated
     public static Map<String, Throwable> getNetworkErrors() {
-        return new HashMap<>(NETWORK_ERRORS);
+        return NetworkManager.getNetworkErrors();
     }
 
     /**
      * Clears the network errors cache.
+     * @deprecated Use {@link NetworkManager#clearNetworkErrors}
      * @since 12011
      */
+    @Deprecated
     public static void clearNetworkErrors() {
-        NETWORK_ERRORS.clear();
+        NetworkManager.clearNetworkErrors();
     }
 
@@ -546,8 +539,10 @@
      * @param r the online resource
      * @return {@code true} if {@code r} is offline and should not be accessed
+     * @deprecated Use {@link NetworkManager#isOffline}
      * @since 7434
      */
+    @Deprecated
     public static boolean isOffline(OnlineResource r) {
-        return OFFLINE_RESOURCES.contains(r) || OFFLINE_RESOURCES.contains(OnlineResource.ALL);
+        return NetworkManager.isOffline(r);
     }
 
@@ -556,8 +551,10 @@
      * @param r the online resource
      * @return {@code true} if {@code r} was not already offline
+     * @deprecated Use {@link NetworkManager#setOffline}
      * @since 7434
      */
+    @Deprecated
     public static boolean setOffline(OnlineResource r) {
-        return OFFLINE_RESOURCES.add(r);
+        return NetworkManager.setOffline(r);
     }
 
@@ -566,8 +563,10 @@
      * @param r the online resource
      * @return {@code true} if {@code r} was offline
+     * @deprecated Use {@link NetworkManager#setOnline}
      * @since 8506
      */
+    @Deprecated
     public static boolean setOnline(OnlineResource r) {
-        return OFFLINE_RESOURCES.remove(r);
+        return NetworkManager.setOnline(r);
     }
 
@@ -575,8 +574,10 @@
      * Replies the set of online resources currently offline.
      * @return the set of online resources currently offline
+     * @deprecated Use {@link NetworkManager#getOfflineResources}
      * @since 7434
      */
+    @Deprecated
     public static Set<OnlineResource> getOfflineResources() {
-        return EnumSet.copyOf(OFFLINE_RESOURCES);
+        return NetworkManager.getOfflineResources();
     }
 }
Index: trunk/src/org/openstreetmap/josm/actions/CloseChangesetAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/CloseChangesetAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/CloseChangesetAction.java	(revision 14121)
@@ -24,4 +24,5 @@
 import org.openstreetmap.josm.gui.io.CloseChangesetTask;
 import org.openstreetmap.josm.io.ChangesetQuery;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmServerChangesetReader;
@@ -52,5 +53,5 @@
         );
         putValue("help", ht("/Action/CloseChangeset"));
-        setEnabled(!Main.isOffline(OnlineResource.OSM_API));
+        setEnabled(!NetworkManager.isOffline(OnlineResource.OSM_API));
 
     }
Index: trunk/src/org/openstreetmap/josm/actions/DownloadNotesInViewAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/DownloadNotesInViewAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/DownloadNotesInViewAction.java	(revision 14121)
@@ -7,5 +7,4 @@
 import java.util.concurrent.Future;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadNotesTask;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadParams;
@@ -13,4 +12,5 @@
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 
@@ -55,5 +55,5 @@
     protected void updateEnabledState() {
         setEnabled(getLayerManager().getActiveLayer() != null
-                && !Main.isOffline(OnlineResource.OSM_API));
+                && !NetworkManager.isOffline(OnlineResource.OSM_API));
     }
 }
Index: trunk/src/org/openstreetmap/josm/actions/DownloadOsmInViewAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/DownloadOsmInViewAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/DownloadOsmInViewAction.java	(revision 14121)
@@ -7,5 +7,4 @@
 import java.util.concurrent.Future;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadParams;
@@ -14,4 +13,5 @@
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.io.BoundingBoxDownloader;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 
@@ -43,5 +43,5 @@
     protected void updateEnabledState() {
         setEnabled(getLayerManager().getActiveLayer() != null
-                && !Main.isOffline(OnlineResource.OSM_API));
+                && !NetworkManager.isOffline(OnlineResource.OSM_API));
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/HelpAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/HelpAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/HelpAction.java	(revision 14121)
@@ -15,4 +15,5 @@
 import org.openstreetmap.josm.gui.help.HelpBrowser;
 import org.openstreetmap.josm.gui.help.HelpUtil;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -35,5 +36,5 @@
                 shortcut ? Shortcut.registerShortcut("system:help", tr("Help"), KeyEvent.VK_F1, Shortcut.DIRECT) : null,
                 true);
-        setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
+        setEnabled(!NetworkManager.isOffline(OnlineResource.JOSM_WEBSITE));
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java	(revision 14121)
@@ -13,4 +13,5 @@
 import org.openstreetmap.josm.gui.dialogs.OsmIdSelectionDialog;
 import org.openstreetmap.josm.gui.history.HistoryBrowserDialogManager;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -67,5 +68,5 @@
         public void setupDialog() {
             super.setupDialog();
-            buttons.get(0).setEnabled(!Main.isOffline(OnlineResource.OSM_API));
+            buttons.get(0).setEnabled(!NetworkManager.isOffline(OnlineResource.OSM_API));
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/UpdateDataAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UpdateDataAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/UpdateDataAction.java	(revision 14121)
@@ -12,9 +12,9 @@
 import java.util.concurrent.Future;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadTaskList;
 import org.openstreetmap.josm.data.DataSource;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.progress.swing.PleaseWaitProgressMonitor;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -48,5 +48,5 @@
     protected void updateEnabledState() {
         OsmDataLayer editLayer = getLayerManager().getEditLayer();
-        setEnabled(editLayer != null && editLayer.isDownloadable() && !Main.isOffline(OnlineResource.OSM_API));
+        setEnabled(editLayer != null && editLayer.isDownloadable() && !NetworkManager.isOffline(OnlineResource.OSM_API));
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/UpdateModifiedAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UpdateModifiedAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/UpdateModifiedAction.java	(revision 14121)
@@ -9,8 +9,8 @@
 import java.util.Collections;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DownloadPolicy;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -49,5 +49,5 @@
         DataSet ds = getLayerManager().getEditDataSet();
         setEnabled(ds != null && !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy())
-                && !Main.isOffline(OnlineResource.OSM_API));
+                && !NetworkManager.isOffline(OnlineResource.OSM_API));
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/UpdateSelectionAction.java	(revision 14121)
@@ -25,4 +25,5 @@
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.io.MultiFetchServerObjectReader;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmTransferException;
@@ -125,5 +126,5 @@
             DataSet ds = selection.iterator().next().getDataSet();
             setEnabled(!ds.isLocked() && !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy())
-                    && !Main.isOffline(OnlineResource.OSM_API));
+                    && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
     }
Index: trunk/src/org/openstreetmap/josm/actions/relation/AbstractRelationAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/relation/AbstractRelationAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/relation/AbstractRelationAction.java	(revision 14121)
@@ -7,5 +7,4 @@
 import javax.swing.AbstractAction;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.IPrimitiveAction;
 import org.openstreetmap.josm.data.osm.DownloadPolicy;
@@ -13,4 +12,5 @@
 import org.openstreetmap.josm.data.osm.IRelation;
 import org.openstreetmap.josm.data.osm.OsmData;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.SubclassFilteredCollection;
@@ -57,5 +57,5 @@
         }
         OsmData<?, ?, ?, ?> ds = relations.iterator().next().getDataSet();
-        return !Main.isOffline(OnlineResource.OSM_API)
+        return !NetworkManager.isOffline(OnlineResource.OSM_API)
             && ds != null && !ds.isLocked() && !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy());
     }
Index: trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/actions/upload/ApiPreconditionCheckerHook.java	(revision 14121)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.gui.MainApplication;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmApi;
@@ -33,5 +34,5 @@
         OsmApi api = OsmApi.getOsmApi();
         try {
-            if (Main.isOffline(OnlineResource.OSM_API)) {
+            if (NetworkManager.isOffline(OnlineResource.OSM_API)) {
                 return false;
             }
Index: trunk/src/org/openstreetmap/josm/data/UserIdentityManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/UserIdentityManager.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/data/UserIdentityManager.java	(revision 14121)
@@ -6,9 +6,9 @@
 import java.text.MessageFormat;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.oauth.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.data.osm.User;
 import org.openstreetmap.josm.data.osm.UserInfo;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmApi;
@@ -67,5 +67,5 @@
             instance = new UserIdentityManager();
             if (OsmApi.isUsingOAuth() && OAuthAccessTokenHolder.getInstance().containsAccessToken() &&
-                    !Main.isOffline(OnlineResource.OSM_API)) {
+                    !NetworkManager.isOffline(OnlineResource.OSM_API)) {
                 try {
                     instance.initFromOAuth();
Index: trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/ExtendedDialog.java	(revision 14121)
@@ -32,5 +32,4 @@
 import javax.swing.UIManager;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.help.HelpBrowser;
 import org.openstreetmap.josm.gui.help.HelpUtil;
@@ -38,4 +37,5 @@
 import org.openstreetmap.josm.gui.util.WindowGeometry;
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.GBC;
@@ -554,5 +554,5 @@
             putValue(NAME, tr("Help"));
             new ImageProvider("help").getResource().attachImageIcon(this, true);
-            setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
+            setEnabled(!NetworkManager.isOffline(OnlineResource.JOSM_WEBSITE));
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 14121)
@@ -147,4 +147,5 @@
 import org.openstreetmap.josm.io.FileWatcher;
 import org.openstreetmap.josm.io.MessageNotifier;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmApi;
@@ -1310,5 +1311,5 @@
             for (String s : offlineNames.split(",")) {
                 try {
-                    Main.setOffline(OnlineResource.valueOf(s.toUpperCase(Locale.ENGLISH)));
+                    NetworkManager.setOffline(OnlineResource.valueOf(s.toUpperCase(Locale.ENGLISH)));
                 } catch (IllegalArgumentException e) {
                     Logging.log(Logging.LEVEL_ERROR,
@@ -1320,5 +1321,5 @@
             }
         }
-        Set<OnlineResource> offline = Main.getOfflineResources();
+        Set<OnlineResource> offline = NetworkManager.getOfflineResources();
         if (!offline.isEmpty()) {
             Logging.warn(trn("JOSM is running in offline mode. This resource will not be available: {0}",
@@ -1508,5 +1509,5 @@
 
         private static boolean handleNetworkErrors() {
-            Map<String, Throwable> networkErrors = Main.getNetworkErrors();
+            Map<String, Throwable> networkErrors = NetworkManager.getNetworkErrors();
             boolean condition = !networkErrors.isEmpty();
             if (condition) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 14121)
@@ -33,5 +33,4 @@
 import javax.swing.event.ListSelectionListener;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AbstractInfoAction;
 import org.openstreetmap.josm.actions.downloadtasks.ChangesetHeaderDownloadTask;
@@ -56,4 +55,5 @@
 import org.openstreetmap.josm.gui.widgets.ListPopupMenu;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -361,5 +361,5 @@
 
         protected void updateEnabledState() {
-            setEnabled(getCurrentChangesetList().getSelectedIndices().length > 0 && !Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(getCurrentChangesetList().getSelectedIndices().length > 0 && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
@@ -498,5 +498,5 @@
         public static void displayChangesets(final Set<Integer> sel) {
             final Set<Integer> toDownload = new HashSet<>();
-            if (!Main.isOffline(OnlineResource.OSM_API)) {
+            if (!NetworkManager.isOffline(OnlineResource.OSM_API)) {
                 ChangesetCache cc = ChangesetCache.getInstance();
                 for (int id: sel) {
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetCacheManager.java	(revision 14121)
@@ -41,5 +41,4 @@
 import javax.swing.event.ListSelectionListener;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.AbstractChangesetDownloadTask;
 import org.openstreetmap.josm.actions.downloadtasks.ChangesetContentDownloadTask;
@@ -64,4 +63,5 @@
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
 import org.openstreetmap.josm.io.ChangesetQuery;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -387,5 +387,5 @@
             new ImageProvider("dialogs", "search").getResource().attachImageIcon(this);
             putValue(SHORT_DESCRIPTION, tr("Launch the dialog for querying changesets"));
-            setEnabled(!Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(!NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
@@ -511,5 +511,5 @@
 
         protected void updateEnabledState() {
-            setEnabled(model.hasSelectedChangesets() && !Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(model.hasSelectedChangesets() && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
@@ -544,5 +544,5 @@
 
         protected void updateEnabledState() {
-            setEnabled(model.hasSelectedChangesets() && !Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(model.hasSelectedChangesets() && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
@@ -584,5 +584,5 @@
 
         protected void updateEnabledState() {
-            setEnabled(model.hasSelectedChangesets() && !Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(model.hasSelectedChangesets() && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
@@ -618,5 +618,5 @@
             new ImageProvider("dialogs/changeset", "downloadchangeset").getResource().attachImageIcon(this);
             putValue(SHORT_DESCRIPTION, tr("Download my changesets from the OSM server (max. 100 changesets)"));
-            setEnabled(!Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(!NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDetailPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDetailPanel.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDetailPanel.java	(revision 14121)
@@ -29,5 +29,4 @@
 import javax.swing.JToolBar;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AutoScaleAction;
 import org.openstreetmap.josm.actions.downloadtasks.ChangesetHeaderDownloadTask;
@@ -45,4 +44,5 @@
 import org.openstreetmap.josm.gui.widgets.JosmTextArea;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -331,5 +331,5 @@
 
         public void initProperties(Changeset cs) {
-            setEnabled(cs != null && !Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(cs != null && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/ChangesetDiscussionPanel.java	(revision 14121)
@@ -20,9 +20,9 @@
 import javax.swing.JToolBar;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.ChangesetHeaderDownloadTask;
 import org.openstreetmap.josm.actions.downloadtasks.PostDownloadHandler;
 import org.openstreetmap.josm.data.osm.Changeset;
 import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -83,5 +83,5 @@
 
         public void initProperties(Changeset cs) {
-            setEnabled(cs != null && !Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(cs != null && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
     }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/SingleChangesetDownloadPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/SingleChangesetDownloadPanel.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/SingleChangesetDownloadPanel.java	(revision 14121)
@@ -17,8 +17,8 @@
 import javax.swing.event.DocumentListener;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.ChangesetContentDownloadTask;
 import org.openstreetmap.josm.gui.widgets.ChangesetIdTextField;
 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -88,5 +88,5 @@
 
         @Override
-        public void actionPerformed(ActionEvent arg0) {
+        public void actionPerformed(ActionEvent e) {
             if (!isEnabled())
                 return;
@@ -102,19 +102,19 @@
 
         protected void updateEnabledState() {
-            setEnabled(tfChangesetId.readIds() && !Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(tfChangesetId.readIds() && !NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
         @Override
-        public void changedUpdate(DocumentEvent arg0) {
+        public void changedUpdate(DocumentEvent e) {
             updateEnabledState();
         }
 
         @Override
-        public void insertUpdate(DocumentEvent arg0) {
+        public void insertUpdate(DocumentEvent e) {
             updateEnabledState();
         }
 
         @Override
-        public void removeUpdate(DocumentEvent arg0) {
+        public void removeUpdate(DocumentEvent e) {
             updateEnabledState();
         }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/relation/actions/AbstractRelationEditorAction.java	(revision 14121)
@@ -12,5 +12,4 @@
 import javax.swing.event.TableModelListener;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.DownloadPolicy;
@@ -22,4 +21,5 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 import org.openstreetmap.josm.gui.tagging.TagEditorModel;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 
@@ -93,5 +93,5 @@
             return false;
         DataSet ds = editorAccess.getEditor().getRelation().getDataSet();
-        return !Main.isOffline(OnlineResource.OSM_API) && ds != null && !ds.isLocked()
+        return !NetworkManager.isOffline(OnlineResource.OSM_API) && ds != null && !ds.isLocked()
                 && !DownloadPolicy.BLOCKED.equals(ds.getDownloadPolicy());
     }
Index: trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java	(revision 14121)
@@ -48,4 +48,5 @@
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.gui.util.WindowGeometry;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.plugins.PluginHandler;
@@ -549,5 +550,5 @@
             new ImageProvider("download").getResource().attachImageIcon(this);
             putValue(SHORT_DESCRIPTION, tr("Click to download the currently selected area"));
-            setEnabled(!Main.isOffline(OnlineResource.OSM_API));
+            setEnabled(!NetworkManager.isOffline(OnlineResource.OSM_API));
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/download/DownloadObjectDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/download/DownloadObjectDialog.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/download/DownloadObjectDialog.java	(revision 14121)
@@ -14,4 +14,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.gui.dialogs.OsmIdSelectionDialog;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -54,5 +55,5 @@
     public void setupDialog() {
         super.setupDialog();
-        buttons.get(0).setEnabled(!Main.isOffline(OnlineResource.OSM_API));
+        buttons.get(0).setEnabled(!NetworkManager.isOffline(OnlineResource.OSM_API));
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/help/ContextSensitiveHelpAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/help/ContextSensitiveHelpAction.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/help/ContextSensitiveHelpAction.java	(revision 14121)
@@ -10,5 +10,5 @@
 import javax.swing.AbstractAction;
 
-import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -48,5 +48,5 @@
         new ImageProvider("help").getResource().attachImageIcon(this);
         this.helpTopic = helpTopic;
-        setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
+        setEnabled(!NetworkManager.isOffline(OnlineResource.JOSM_WEBSITE));
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/SourceEditor.java	(revision 14121)
@@ -91,4 +91,5 @@
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
 import org.openstreetmap.josm.io.CachedFile;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OnlineResource;
 import org.openstreetmap.josm.io.OsmTransferException;
@@ -1155,5 +1156,5 @@
             this.url = url;
             this.sourceProviders = sourceProviders;
-            setEnabled(!Main.isOffline(OnlineResource.JOSM_WEBSITE));
+            setEnabled(!NetworkManager.isOffline(OnlineResource.JOSM_WEBSITE));
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java	(revision 14121)
@@ -42,4 +42,5 @@
 import org.openstreetmap.josm.gui.tagging.presets.items.Text;
 import org.openstreetmap.josm.io.CachedFile;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.UTFInputStreamReader;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -386,5 +387,5 @@
                 Logging.error(source);
                 if (source.startsWith("http")) {
-                    Main.addNetworkError(source, e);
+                    NetworkManager.addNetworkError(source, e);
                 }
                 if (displayErrMsg) {
Index: trunk/src/org/openstreetmap/josm/io/MessageNotifier.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/MessageNotifier.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/io/MessageNotifier.java	(revision 14121)
@@ -10,5 +10,4 @@
 import java.util.concurrent.TimeUnit;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.data.osm.UserInfo;
@@ -100,5 +99,5 @@
     public static void start() {
         int interval = PROP_INTERVAL.get();
-        if (Main.isOffline(OnlineResource.OSM_API)) {
+        if (NetworkManager.isOffline(OnlineResource.OSM_API)) {
             Logging.info(tr("{0} not available (offline mode)", tr("Message notifier")));
         } else if (!isRunning() && interval > 0 && isUserEnoughIdentified()) {
Index: trunk/src/org/openstreetmap/josm/io/NetworkManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/NetworkManager.java	(revision 14121)
+++ trunk/src/org/openstreetmap/josm/io/NetworkManager.java	(revision 14121)
@@ -0,0 +1,109 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import java.net.URL;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.openstreetmap.josm.tools.Logging;
+
+/**
+ * Handles global network features (errors and online/offline resources).
+ * @since 14121
+ */
+public final class NetworkManager {
+
+    private static final Map<String, Throwable> NETWORK_ERRORS = new HashMap<>();
+
+    private static final Set<OnlineResource> OFFLINE_RESOURCES = EnumSet.noneOf(OnlineResource.class);
+
+    private NetworkManager() {
+        // Hide constructor
+    }
+
+    /**
+     * Adds a new network error that occur to give a hint about broken Internet connection.
+     * Do not use this method for errors known for sure thrown because of a bad proxy configuration.
+     *
+     * @param url The accessed URL that caused the error
+     * @param t The network error
+     * @return The previous error associated to the given resource, if any. Can be {@code null}
+     */
+    public static Throwable addNetworkError(String url, Throwable t) {
+        if (url != null && t != null) {
+            return NETWORK_ERRORS.put(url, t);
+        }
+        return null;
+    }
+
+    /**
+     * Adds a new network error that occur to give a hint about broken Internet connection.
+     * Do not use this method for errors known for sure thrown because of a bad proxy configuration.
+     *
+     * @param url The accessed URL that caused the error
+     * @param t The network error
+     * @return The previous error associated to the given resource, if any. Can be {@code null}
+     */
+    public static Throwable addNetworkError(URL url, Throwable t) {
+        if (url != null && t != null) {
+            Throwable old = addNetworkError(url.toExternalForm(), t);
+            if (old != null) {
+                Logging.warn("Already here "+old);
+            }
+            return old;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the network errors that occured until now.
+     * @return the network errors that occured until now, indexed by URL
+     */
+    public static Map<String, Throwable> getNetworkErrors() {
+        return new HashMap<>(NETWORK_ERRORS);
+    }
+
+    /**
+     * Clears the network errors cache.
+     */
+    public static void clearNetworkErrors() {
+        NETWORK_ERRORS.clear();
+    }
+
+    /**
+     * Determines if the given online resource is currently offline.
+     * @param r the online resource
+     * @return {@code true} if {@code r} is offline and should not be accessed
+     */
+    public static boolean isOffline(OnlineResource r) {
+        return OFFLINE_RESOURCES.contains(r) || OFFLINE_RESOURCES.contains(OnlineResource.ALL);
+    }
+
+    /**
+     * Sets the given online resource to offline state.
+     * @param r the online resource
+     * @return {@code true} if {@code r} was not already offline
+     */
+    public static boolean setOffline(OnlineResource r) {
+        return OFFLINE_RESOURCES.add(r);
+    }
+
+    /**
+     * Sets the given online resource to online state.
+     * @param r the online resource
+     * @return {@code true} if {@code r} was offline
+     */
+    public static boolean setOnline(OnlineResource r) {
+        return OFFLINE_RESOURCES.remove(r);
+    }
+
+    /**
+     * Replies the set of online resources currently offline.
+     * @return the set of online resources currently offline
+     */
+    public static Set<OnlineResource> getOfflineResources() {
+        return EnumSet.copyOf(OFFLINE_RESOURCES);
+    }
+}
Index: trunk/src/org/openstreetmap/josm/io/OnlineResource.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OnlineResource.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/io/OnlineResource.java	(revision 14121)
@@ -3,6 +3,4 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
-
-import org.openstreetmap.josm.Main;
 
 /**
@@ -43,5 +41,5 @@
      */
     public final void checkOfflineAccess(String downloadString, String resourceString) {
-        if (Main.isOffline(this) && downloadString.substring(downloadString.indexOf("://"))
+        if (NetworkManager.isOffline(this) && downloadString.substring(downloadString.indexOf("://"))
                 .startsWith(resourceString.substring(resourceString.indexOf("://")))) {
             throw new OfflineAccessException(tr("Unable to access ''{0}'': {1} not available (offline mode)", downloadString, getLocName()));
Index: trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 14121)
@@ -25,5 +25,4 @@
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.notes.Note;
@@ -259,5 +258,5 @@
             }
             if (capabilities == null) {
-                if (Main.isOffline(OnlineResource.OSM_API)) {
+                if (NetworkManager.isOffline(OnlineResource.OSM_API)) {
                     Logging.warn(tr("{0} not available (offline mode)", tr("OSM API")));
                 } else {
@@ -280,5 +279,5 @@
         } catch (OsmTransferException e) {
             initialized = false;
-            Main.addNetworkError(url, Utils.getRootCause(e));
+            NetworkManager.addNetworkError(url, Utils.getRootCause(e));
             throw new OsmApiInitializationException(e);
         } catch (SAXException | IOException | ParserConfigurationException e) {
Index: trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 14121)
@@ -67,4 +67,5 @@
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
 import org.openstreetmap.josm.gui.widgets.JosmTextArea;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.OfflineAccessException;
 import org.openstreetmap.josm.io.OnlineResource;
@@ -530,8 +531,8 @@
 
     private static boolean checkOfflineAccess() {
-        if (Main.isOffline(OnlineResource.ALL)) {
+        if (NetworkManager.isOffline(OnlineResource.ALL)) {
             return false;
         }
-        if (Main.isOffline(OnlineResource.JOSM_WEBSITE)) {
+        if (NetworkManager.isOffline(OnlineResource.JOSM_WEBSITE)) {
             for (String updateSite : Main.pref.getPluginSites()) {
                 try {
Index: trunk/src/org/openstreetmap/josm/tools/HttpClient.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/HttpClient.java	(revision 14120)
+++ trunk/src/org/openstreetmap/josm/tools/HttpClient.java	(revision 14121)
@@ -29,9 +29,9 @@
 import java.util.zip.GZIPInputStream;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
 import org.openstreetmap.josm.io.Compression;
+import org.openstreetmap.josm.io.NetworkManager;
 import org.openstreetmap.josm.io.ProgressInputStream;
 import org.openstreetmap.josm.io.ProgressOutputStream;
@@ -162,5 +162,5 @@
                 Logging.warn(e);
                 //noinspection ThrowableResultOfMethodCallIgnored
-                Main.addNetworkError(url, Utils.getRootCause(e));
+                NetworkManager.addNetworkError(url, Utils.getRootCause(e));
                 throw e;
             }
