Index: trunk/src/org/openstreetmap/josm/Main.java
===================================================================
--- trunk/src/org/openstreetmap/josm/Main.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/Main.java	(revision 14119)
@@ -40,6 +40,6 @@
 import org.openstreetmap.josm.io.FileWatcher;
 import org.openstreetmap.josm.io.OnlineResource;
-import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.spi.preferences.IUrls;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -58,16 +58,4 @@
  */
 public abstract class Main {
-
-    /**
-     * The JOSM website URL.
-     * @since 6897 (was public from 6143 to 6896)
-     */
-    private static final String JOSM_WEBSITE = "https://josm.openstreetmap.de";
-
-    /**
-     * The OSM website URL.
-     * @since 6897 (was public from 6453 to 6896)
-     */
-    private static final String OSM_WEBSITE = "https://www.openstreetmap.org";
 
     /**
@@ -539,10 +527,10 @@
      * Returns the JOSM website URL.
      * @return the josm website URL
+     * @deprecated Use {@link IUrls#getJOSMWebsite}
      * @since 6897
      */
+    @Deprecated
     public static String getJOSMWebsite() {
-        if (Config.getPref() != null)
-            return Config.getPref().get("josm.url", JOSM_WEBSITE);
-        return JOSM_WEBSITE;
+        return Config.getUrls().getJOSMWebsite();
     }
 
@@ -550,9 +538,10 @@
      * Returns the JOSM XML URL.
      * @return the josm XML URL
+     * @deprecated Use {@link IUrls#getXMLBase}
      * @since 6897
      */
+    @Deprecated
     public static String getXMLBase() {
-        // Always return HTTP (issues reported with HTTPS)
-        return "http://josm.openstreetmap.de";
+        return Config.getUrls().getXMLBase();
     }
 
@@ -560,23 +549,10 @@
      * Returns the OSM website URL.
      * @return the OSM website URL
+     * @deprecated Use {@link IUrls#getOSMWebsite}
      * @since 6897
      */
+    @Deprecated
     public static String getOSMWebsite() {
-        if (Config.getPref() != null)
-            return Config.getPref().get("osm.url", OSM_WEBSITE);
-        return OSM_WEBSITE;
-    }
-
-    /**
-     * Returns the OSM website URL depending on the selected {@link OsmApi}.
-     * @return the OSM website URL depending on the selected {@link OsmApi}
-     */
-    private static String getOSMWebsiteDependingOnSelectedApi() {
-        final String api = OsmApi.getOsmApi().getServerUrl();
-        if (OsmApi.DEFAULT_API_URL.equals(api)) {
-            return getOSMWebsite();
-        } else {
-            return api.replaceAll("/api$", "");
-        }
+        return Config.getUrls().getOSMWebsite();
     }
 
@@ -584,10 +560,10 @@
      * Replies the base URL for browsing information about a primitive.
      * @return the base URL, i.e. https://www.openstreetmap.org
+     * @deprecated Use {@link IUrls#getBaseBrowseUrl}
      * @since 7678
      */
+    @Deprecated
     public static String getBaseBrowseUrl() {
-        if (Config.getPref() != null)
-            return Config.getPref().get("osm-browse.url", getOSMWebsiteDependingOnSelectedApi());
-        return getOSMWebsiteDependingOnSelectedApi();
+        return Config.getUrls().getBaseBrowseUrl();
     }
 
@@ -595,10 +571,10 @@
      * Replies the base URL for browsing information about a user.
      * @return the base URL, i.e. https://www.openstreetmap.org/user
+     * @deprecated Use {@link IUrls#getBaseUserUrl}
      * @since 7678
      */
+    @Deprecated
     public static String getBaseUserUrl() {
-        if (Config.getPref() != null)
-            return Config.getPref().get("osm-user.url", getOSMWebsiteDependingOnSelectedApi() + "/user");
-        return getOSMWebsiteDependingOnSelectedApi() + "/user";
+        return Config.getUrls().getBaseUserUrl();
     }
 
Index: trunk/src/org/openstreetmap/josm/actions/AboutAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/AboutAction.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/actions/AboutAction.java	(revision 14119)
@@ -33,4 +33,5 @@
 import org.openstreetmap.josm.gui.widgets.UrlLabel;
 import org.openstreetmap.josm.plugins.PluginHandler;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -100,5 +101,5 @@
         info.add(label, GBC.eol().fill(GBC.HORIZONTAL).insets(10, 0, 0, 10));
         info.add(new JLabel(tr("Homepage")), GBC.std().insets(10, 0, 10, 0));
-        info.add(new UrlLabel(Main.getJOSMWebsite(), 2), GBC.eol());
+        info.add(new UrlLabel(Config.getUrls().getJOSMWebsite(), 2), GBC.eol());
         info.add(new JLabel(tr("Translations")), GBC.std().insets(10, 0, 10, 0));
         info.add(new UrlLabel("https://translations.launchpad.net/josm", 2), GBC.eol());
Index: trunk/src/org/openstreetmap/josm/actions/HistoryInfoWebAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/HistoryInfoWebAction.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/actions/HistoryInfoWebAction.java	(revision 14119)
@@ -7,7 +7,7 @@
 import java.awt.event.KeyEvent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.osm.IPrimitive;
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -34,5 +34,6 @@
         if (infoObject instanceof IPrimitive) {
             IPrimitive primitive = (IPrimitive) infoObject;
-            return Main.getBaseBrowseUrl() + '/' + OsmPrimitiveType.from(primitive).getAPIName() + '/' + primitive.getOsmId() + "/history";
+            return Config.getUrls().getBaseBrowseUrl()
+                    + '/' + OsmPrimitiveType.from(primitive).getAPIName() + '/' + primitive.getOsmId() + "/history";
         } else {
             return null;
Index: trunk/src/org/openstreetmap/josm/actions/InfoWebAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/InfoWebAction.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/actions/InfoWebAction.java	(revision 14119)
@@ -8,5 +8,4 @@
 import java.util.Collection;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.notes.Note;
 import org.openstreetmap.josm.data.osm.IPrimitive;
@@ -14,4 +13,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.gui.MainApplication;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -38,8 +38,8 @@
         if (infoObject instanceof IPrimitive) {
             IPrimitive primitive = (IPrimitive) infoObject;
-            return Main.getBaseBrowseUrl() + '/' + OsmPrimitiveType.from(primitive).getAPIName() + '/' + primitive.getOsmId();
+            return Config.getUrls().getBaseBrowseUrl() + '/' + OsmPrimitiveType.from(primitive).getAPIName() + '/' + primitive.getOsmId();
         } else if (infoObject instanceof Note) {
             Note note = (Note) infoObject;
-            return Main.getBaseBrowseUrl() + "/note/" + note.getId();
+            return Config.getUrls().getBaseBrowseUrl() + "/note/" + note.getId();
         } else {
             return null;
Index: trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 14119)
@@ -198,5 +198,5 @@
 
         String osmApi = OsmApi.getOsmApi().getServerUrl();
-        if (!OsmApi.DEFAULT_API_URL.equals(osmApi.trim())) {
+        if (!Config.getUrls().getDefaultOsmApiUrl().equals(osmApi.trim())) {
             text.append("OSM API: ").append(osmApi).append("\n\n");
         }
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 14119)
@@ -715,5 +715,5 @@
      */
     public Collection<String> getPluginSites() {
-        return getList("pluginmanager.sites", Collections.singletonList(Main.getJOSMWebsite()+"/pluginicons%<?plugins=>"));
+        return getList("pluginmanager.sites", Collections.singletonList(Config.getUrls().getJOSMWebsite()+"/pluginicons%<?plugins=>"));
     }
 
@@ -727,5 +727,5 @@
         for (Iterator<String> it = pluginSites.iterator(); it.hasNext();) {
             try {
-                OnlineResource.JOSM_WEBSITE.checkOfflineAccess(it.next(), Main.getJOSMWebsite());
+                OnlineResource.JOSM_WEBSITE.checkOfflineAccess(it.next(), Config.getUrls().getJOSMWebsite());
             } catch (OfflineAccessException ex) {
                 Logging.log(Logging.LEVEL_WARN, ex);
Index: trunk/src/org/openstreetmap/josm/data/gpx/GpxConstants.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/gpx/GpxConstants.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/data/gpx/GpxConstants.java	(revision 14119)
@@ -7,6 +7,6 @@
 import java.util.List;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.spi.preferences.Config;
 
 /**
@@ -103,5 +103,5 @@
      * A namespace for josm GPX extensions
      */
-    String JOSM_EXTENSIONS_NAMESPACE_URI = Main.getXMLBase() + "/gpx-extensions-1.0";
+    String JOSM_EXTENSIONS_NAMESPACE_URI = Config.getUrls().getXMLBase() + "/gpx-extensions-1.0";
 
     /** Elevation (in meters) of the point. */
Index: trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java	(revision 14119)
@@ -18,5 +18,4 @@
 import java.util.concurrent.ExecutorService;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.StructUtils;
 import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry;
@@ -50,5 +49,5 @@
 
     private static final String[] DEFAULT_LAYER_SITES = {
-        Main.getJOSMWebsite()+"/maps%<?ids=>"
+            Config.getUrls().getJOSMWebsite()+"/maps%<?ids=>"
     };
 
@@ -162,5 +161,5 @@
             boolean online = true;
             try {
-                OnlineResource.JOSM_WEBSITE.checkOfflineAccess(source, Main.getJOSMWebsite());
+                OnlineResource.JOSM_WEBSITE.checkOfflineAccess(source, Config.getUrls().getJOSMWebsite());
             } catch (OfflineAccessException e) {
                 Logging.log(Logging.LEVEL_WARN, e);
Index: trunk/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/data/oauth/OAuthParameters.java	(revision 14119)
@@ -4,5 +4,4 @@
 import java.util.Objects;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.spi.preferences.Config;
@@ -56,5 +55,5 @@
         }
 
-        if (apiUrl != null && !OsmApi.DEFAULT_API_URL.equals(apiUrl)) {
+        if (apiUrl != null && !Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl)) {
             consumerKey = ""; // a custom consumer key is required
             consumerSecret = ""; // a custom consumer secret is requireds
@@ -63,5 +62,5 @@
             consumerKey = DEFAULT_JOSM_CONSUMER_KEY;
             consumerSecret = DEFAULT_JOSM_CONSUMER_SECRET;
-            serverUrl = Main.getOSMWebsite();
+            serverUrl = Config.getUrls().getOSMWebsite();
         }
 
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 14119)
@@ -55,4 +55,5 @@
 import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
 import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ListenerList;
 import org.openstreetmap.josm.tools.Logging;
@@ -772,5 +773,5 @@
                     "JOSM expected to find primitive [{0} {1}] in dataset but it is not there. Please report this "
                             + "at {2}. This is not a critical error, it should be safe to continue in your work.",
-                    primitiveId.getType(), Long.toString(primitiveId.getUniqueId()), Main.getJOSMWebsite()));
+                    primitiveId.getType(), Long.toString(primitiveId.getUniqueId()), Config.getUrls().getJOSMWebsite()));
             Logging.error(new Exception());
         }
Index: trunk/src/org/openstreetmap/josm/data/preferences/JosmUrls.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/JosmUrls.java	(revision 14119)
+++ trunk/src/org/openstreetmap/josm/data/preferences/JosmUrls.java	(revision 14119)
@@ -0,0 +1,93 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.preferences;
+
+import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.spi.preferences.IUrls;
+
+/**
+ * Class that provides URLs values for JOSM.
+ * @since 14119
+ */
+public final class JosmUrls implements IUrls {
+
+    /**
+     * The JOSM website URL.
+     */
+    private static final String JOSM_WEBSITE = "https://josm.openstreetmap.de";
+
+    /**
+     * The OSM website URL.
+     */
+    private static final String OSM_WEBSITE = "https://www.openstreetmap.org";
+
+    /**
+     * public URL of the standard OSM API.
+     */
+    private static final String DEFAULT_API_URL = "https://api.openstreetmap.org/api";
+
+    private JosmUrls() {
+        // hide constructor
+    }
+
+    private static class InstanceHolder {
+        static final JosmUrls INSTANCE = new JosmUrls();
+    }
+
+    /**
+     * Returns the unique instance.
+     * @return the unique instance
+     */
+    public static JosmUrls getInstance() {
+        return InstanceHolder.INSTANCE;
+    }
+
+    @Override
+    public String getOSMWebsiteDependingOnSelectedApi() {
+        final String api = OsmApi.getOsmApi().getServerUrl();
+        if (DEFAULT_API_URL.equals(api)) {
+            return getOSMWebsite();
+        } else {
+            return api.replaceAll("/api$", "");
+        }
+    }
+
+    @Override
+    public String getBaseBrowseUrl() {
+        if (Config.getPref() != null)
+            return Config.getPref().get("osm-browse.url", getOSMWebsiteDependingOnSelectedApi());
+        return getOSMWebsiteDependingOnSelectedApi();
+    }
+
+    @Override
+    public String getBaseUserUrl() {
+        if (Config.getPref() != null)
+            return Config.getPref().get("osm-user.url", getOSMWebsiteDependingOnSelectedApi() + "/user");
+        return getOSMWebsiteDependingOnSelectedApi() + "/user";
+    }
+
+    @Override
+    public String getJOSMWebsite() {
+        if (Config.getPref() != null)
+            return Config.getPref().get("josm.url", JOSM_WEBSITE);
+        return JOSM_WEBSITE;
+    }
+
+    @Override
+    public String getXMLBase() {
+        // Always return HTTP (issues reported with HTTPS)
+        return "http://josm.openstreetmap.de";
+    }
+
+    @Override
+    public String getOSMWebsite() {
+        if (Config.getPref() != null)
+            return Config.getPref().get("osm.url", OSM_WEBSITE);
+        return OSM_WEBSITE;
+    }
+
+    @Override
+    public String getDefaultOsmApiUrl() {
+        return DEFAULT_API_URL;
+    }
+}
Index: trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/data/preferences/PreferencesWriter.java	(revision 14119)
@@ -9,12 +9,12 @@
 import java.util.stream.Stream;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.io.XmlWriter;
-import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.spi.preferences.ListListSetting;
-import org.openstreetmap.josm.spi.preferences.SettingVisitor;
 import org.openstreetmap.josm.spi.preferences.ListSetting;
 import org.openstreetmap.josm.spi.preferences.MapListSetting;
+import org.openstreetmap.josm.spi.preferences.Setting;
+import org.openstreetmap.josm.spi.preferences.SettingVisitor;
 import org.openstreetmap.josm.spi.preferences.StringSetting;
 
@@ -57,5 +57,5 @@
         out.write(String.format("<?xml version=\"1.0\" encoding=\"UTF-8\"?>%n"));
         String rootElement = defaults ? "preferences-defaults" : "preferences";
-        out.write(String.format("<%s xmlns='%s/preferences-1.0'", rootElement, Main.getXMLBase()));
+        out.write(String.format("<%s xmlns='%s/preferences-1.0'", rootElement, Config.getUrls().getXMLBase()));
         if (defaults) {
             out.write(" xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'");
Index: trunk/src/org/openstreetmap/josm/gui/GettingStarted.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/GettingStarted.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/GettingStarted.java	(revision 14119)
@@ -19,5 +19,4 @@
 import javax.swing.event.HyperlinkListener;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.DownloadPrimitiveAction;
 import org.openstreetmap.josm.data.Version;
@@ -105,5 +104,5 @@
         @Override
         protected void checkOfflineAccess() {
-            OnlineResource.JOSM_WEBSITE.checkOfflineAccess(new WikiReader().getBaseUrlWiki(), Main.getJOSMWebsite());
+            OnlineResource.JOSM_WEBSITE.checkOfflineAccess(new WikiReader().getBaseUrlWiki(), Config.getUrls().getJOSMWebsite());
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 14119)
@@ -100,4 +100,5 @@
 import org.openstreetmap.josm.data.osm.search.SearchMode;
 import org.openstreetmap.josm.data.preferences.JosmBaseDirectories;
+import org.openstreetmap.josm.data.preferences.JosmUrls;
 import org.openstreetmap.josm.data.preferences.sources.SourceType;
 import org.openstreetmap.josm.data.projection.ProjectionCLI;
@@ -298,5 +299,5 @@
      */
     public static final NTV2GridShiftFileSource JOSM_WEBSITE_NTV2_SOURCE = gridFileName -> {
-        String location = Main.getJOSMWebsite() + "/proj/" + gridFileName;
+        String location = Config.getUrls().getJOSMWebsite() + "/proj/" + gridFileName;
         // Try to load grid file
         CachedFile cf = new CachedFile(location);
@@ -918,4 +919,5 @@
         Config.setPreferencesInstance(Main.pref);
         Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance());
+        Config.setUrlsProvider(JosmUrls.getInstance());
 
         if (args.showVersion()) {
@@ -1566,5 +1568,5 @@
                     userInfo.getUnreadMessages(), userInfo.getUnreadMessages())),
                     GBC.eol());
-            panel.add(new UrlLabel(Main.getBaseUserUrl() + '/' + userInfo.getDisplayName() + "/inbox",
+            panel.add(new UrlLabel(Config.getUrls().getBaseUserUrl() + '/' + userInfo.getDisplayName() + "/inbox",
                     tr("Click here to see your inbox.")), GBC.eol());
             panel.setOpaque(false);
Index: trunk/src/org/openstreetmap/josm/gui/bugreport/BugReportDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/bugreport/BugReportDialog.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/bugreport/BugReportDialog.java	(revision 14119)
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.plugins.PluginDownloadTask;
 import org.openstreetmap.josm.plugins.PluginHandler;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -74,5 +75,5 @@
                         tr("Opening the bug report failed. Please report manually using this website:")),
                         GBC.eol().fill(GridBagConstraints.HORIZONTAL));
-                errorPanel.add(new UrlLabel(Main.getJOSMWebsite() + "/newticket", 2), GBC.eop().insets(8, 0, 0, 0));
+                errorPanel.add(new UrlLabel(Config.getUrls().getJOSMWebsite() + "/newticket", 2), GBC.eop().insets(8, 0, 0, 0));
                 errorPanel.add(new DebugTextDisplay(statusText));
 
@@ -142,5 +143,5 @@
 
         panel.add(new JLabel(tr("Manually report at:")+' '), GBC.std());
-        panel.add(new UrlLabel(Main.getJOSMWebsite() + "/newticket"), GBC.std().fill(GBC.HORIZONTAL));
+        panel.add(new UrlLabel(Config.getUrls().getJOSMWebsite() + "/newticket"), GBC.std().fill(GBC.HORIZONTAL));
         JButton copy = new JButton("Copy to clipboard");
         copy.addActionListener(e -> textPanel.copyToClipboard());
Index: trunk/src/org/openstreetmap/josm/gui/bugreport/JosmUpdatePanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/bugreport/JosmUpdatePanel.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/bugreport/JosmUpdatePanel.java	(revision 14119)
@@ -17,4 +17,5 @@
 import org.openstreetmap.josm.gui.widgets.UrlLabel;
 import org.openstreetmap.josm.io.CachedFile;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -61,5 +62,5 @@
 
     private static int getTestedVersion() {
-        try (CachedFile testedVersion = new CachedFile(Main.getJOSMWebsite() + "/tested")) {
+        try (CachedFile testedVersion = new CachedFile(Config.getUrls().getJOSMWebsite() + "/tested")) {
             testedVersion.setMaxAge(60L * 15); // 15 Minutes
             String testedString = new String(testedVersion.getByteContent(), StandardCharsets.ISO_8859_1);
@@ -91,5 +92,5 @@
     private void showUpdateButton() {
         add(new JMultilineLabel(tr("Before you file a bug report make sure you have updated to the latest version of JOSM here:")), GBC.eol());
-        add(new UrlLabel(Main.getJOSMWebsite(), 2), GBC.eop().insets(8, 0, 0, 0));
+        add(new UrlLabel(Config.getUrls().getJOSMWebsite(), 2), GBC.eop().insets(8, 0, 0, 0));
         JButton updateButton = new JButton(tr("Update JOSM"), ImageProvider.getIfAvailable("download"));
         updateButton.addActionListener(e -> openJosmUpdateSite());
@@ -99,5 +100,5 @@
     private static void openJosmUpdateSite() {
         try {
-            Main.platform.openUrl(Main.getJOSMWebsite());
+            Main.platform.openUrl(Config.getUrls().getJOSMWebsite());
         } catch (IOException ex) {
             Logging.log(Logging.LEVEL_WARN, "Unable to access JOSM website:", ex);
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/ChangesetDialog.java	(revision 14119)
@@ -429,5 +429,5 @@
             if (sel.size() > 10 && !AbstractInfoAction.confirmLaunchMultiple(sel.size()))
                 return;
-            String baseUrl = Main.getBaseBrowseUrl();
+            String baseUrl = Config.getUrls().getBaseBrowseUrl();
             for (Changeset cs: sel) {
                 OpenBrowser.displayUrl(baseUrl + "/changeset/" + cs.getId());
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/NotesDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/NotesDialog.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/NotesDialog.java	(revision 14119)
@@ -47,4 +47,5 @@
 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
 import org.openstreetmap.josm.gui.layer.NoteLayer;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.OpenBrowser;
@@ -432,5 +433,5 @@
             final Note note = displayList.getSelectedValue();
             if (note.getId() > 0) {
-                final String url = Main.getBaseBrowseUrl() + "/note/" + note.getId();
+                final String url = Config.getUrls().getBaseBrowseUrl() + "/note/" + note.getId();
                 OpenBrowser.displayUrl(url);
             }
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/UserListDialog.java	(revision 14119)
@@ -31,5 +31,4 @@
 import javax.swing.table.DefaultTableModel;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AbstractInfoAction;
 import org.openstreetmap.josm.data.osm.DataSelectionListener;
@@ -48,4 +47,5 @@
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -237,5 +237,5 @@
             if (infoObject instanceof User) {
                 User user = (User) infoObject;
-                return Main.getBaseUserUrl() + '/' + Utils.encodeUrl(user.getName()).replaceAll("\\+", "%20");
+                return Config.getUrls().getBaseUserUrl() + '/' + Utils.encodeUrl(user.getName()).replaceAll("\\+", "%20");
             } else {
                 return null;
Index: trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/UrlBasedQueryPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/UrlBasedQueryPanel.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/UrlBasedQueryPanel.java	(revision 14119)
@@ -23,5 +23,4 @@
 import javax.swing.event.HyperlinkEvent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
@@ -29,4 +28,5 @@
 import org.openstreetmap.josm.io.ChangesetQuery.ChangesetQueryUrlException;
 import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -80,5 +80,5 @@
     protected static List<String> getExamples() {
         return Arrays.asList(
-                Main.getOSMWebsite()+"/history?open=true",
+                Config.getUrls().getOSMWebsite()+"/history?open=true",
                 OsmApi.getOsmApi().getBaseUrl()+"/changesets?open=true");
     }
Index: trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryWizardDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryWizardDialog.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/download/OverpassQueryWizardDialog.java	(revision 14119)
@@ -20,5 +20,4 @@
 import javax.swing.text.JTextComponent;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.preferences.ListProperty;
 import org.openstreetmap.josm.gui.ExtendedDialog;
@@ -26,4 +25,5 @@
 import org.openstreetmap.josm.gui.util.GuiHelper;
 import org.openstreetmap.josm.gui.widgets.HistoryComboBox;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.Logging;
@@ -196,5 +196,5 @@
                 .append(tr("The <i>Query Wizard</i> tool will transform those to a valid overpass query."))
                 .append(tr("For more detailed description see "))
-                .append(tr("<a href=\"{0}\">OSM Wiki</a>.", Main.getOSMWebsite() + "/wiki/Overpass_turbo/Wizard"))
+                .append(tr("<a href=\"{0}\">OSM Wiki</a>.", Config.getUrls().getOSMWebsite() + "/wiki/Overpass_turbo/Wizard"))
                 .append("</p>")
                 .append(HEADLINE_START).append(tr("Hints")).append(HEADLINE_END)
Index: trunk/src/org/openstreetmap/josm/gui/help/HelpUtil.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/help/HelpUtil.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/help/HelpUtil.java	(revision 14119)
@@ -11,5 +11,4 @@
 import javax.swing.KeyStroke;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.HelpAction;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -34,5 +33,5 @@
      */
     public static String getWikiBaseUrl() {
-        return Config.getPref().get("help.baseurl", Main.getJOSMWebsite());
+        return Config.getPref().get("help.baseurl", Config.getUrls().getJOSMWebsite());
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/history/OpenChangesetPopupMenu.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/OpenChangesetPopupMenu.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/history/OpenChangesetPopupMenu.java	(revision 14119)
@@ -15,5 +15,4 @@
 import javax.swing.JPopupMenu;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.StructUtils;
 import org.openstreetmap.josm.data.StructUtils.StructEntry;
@@ -52,5 +51,5 @@
 
     private static final List<ChangesetViewerEntry> DEFAULT_ENTRIES = Arrays.asList(
-            new ChangesetViewerEntry(tr("View changeset in web browser"), Main.getBaseBrowseUrl() + "/changeset/{0}"),
+            new ChangesetViewerEntry(tr("View changeset in web browser"), Config.getUrls().getBaseBrowseUrl() + "/changeset/{0}"),
             new ChangesetViewerEntry(tr("Open {0}", "achavi (Augmented OSM Change Viewer)"), "https://overpass-api.de/achavi/?changeset={0}"),
             new ChangesetViewerEntry(tr("Open {0}", "OSMCha (OSM Changeset Analyzer)"), "https://osmcha.mapbox.com/changesets/{0}"),
Index: trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java	(revision 14119)
@@ -26,5 +26,4 @@
 import javax.swing.plaf.basic.BasicArrowButton;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.UserIdentityManager;
 import org.openstreetmap.josm.data.osm.Changeset;
@@ -39,4 +38,5 @@
 import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
 import org.openstreetmap.josm.gui.widgets.UrlLabel;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.GBC;
@@ -215,5 +215,5 @@
 
     protected static String getUserUrl(String username) {
-        return Main.getBaseUserUrl() + '/' + Utils.encodeUrl(username).replaceAll("\\+", "%20");
+        return Config.getUrls().getBaseUserUrl() + '/' + Utils.encodeUrl(username).replaceAll("\\+", "%20");
     }
 
@@ -248,5 +248,5 @@
         if (!isLatest && cs != null) {
             User user = cs.getUser();
-            String url = Main.getBaseBrowseUrl() + "/changeset/" + cs.getId();
+            String url = Config.getUrls().getBaseBrowseUrl() + "/changeset/" + cs.getId();
             lblChangeset.setUrl(url);
             lblChangeset.setDescription(Long.toString(cs.getId()));
Index: trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/history/VersionTable.java	(revision 14119)
@@ -27,5 +27,4 @@
 import javax.swing.table.TableCellRenderer;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AbstractInfoAction;
 import org.openstreetmap.josm.data.osm.User;
@@ -162,5 +161,5 @@
             if (infoObject instanceof HistoryOsmPrimitive) {
                 HistoryOsmPrimitive prim = (HistoryOsmPrimitive) infoObject;
-                return Main.getBaseBrowseUrl() + "/changeset/" + prim.getChangesetId();
+                return Config.getUrls().getBaseBrowseUrl() + "/changeset/" + prim.getChangesetId();
             } else {
                 return null;
@@ -199,5 +198,5 @@
             if (infoObject instanceof HistoryOsmPrimitive) {
                 HistoryOsmPrimitive hp = (HistoryOsmPrimitive) infoObject;
-                return hp.getUser() == null ? null : Main.getBaseUserUrl() + '/' + hp.getUser().getName();
+                return hp.getUser() == null ? null : Config.getUrls().getBaseUserUrl() + '/' + hp.getUser().getName();
             } else {
                 return null;
Index: trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/io/UploadPrimitivesTask.java	(revision 14119)
@@ -40,4 +40,5 @@
 import org.openstreetmap.josm.io.OsmTransferException;
 import org.openstreetmap.josm.io.UploadStrategySpecification;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -342,5 +343,5 @@
             if (lastException == null) {
                 HtmlPanel panel = new HtmlPanel(
-                        "<h3><a href=\"" + Main.getBaseBrowseUrl() + "/changeset/" + changeset.getId() + "\">"
+                        "<h3><a href=\"" + Config.getUrls().getBaseBrowseUrl() + "/changeset/" + changeset.getId() + "\">"
                                 + tr("Upload successful!") + "</a></h3>");
                 panel.enableClickableHyperlinks();
Index: trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/layer/gpx/ConvertToDataLayerAction.java	(revision 14119)
@@ -366,5 +366,5 @@
                         + "If you want to upload traces, look here:</html>")),
                 GBC.eol());
-        msg.add(new UrlLabel(Main.getOSMWebsite() + "/traces", 2), GBC.eop());
+        msg.add(new UrlLabel(Config.getUrls().getOSMWebsite() + "/traces", 2), GBC.eop());
         if (!ConditionalOptionPaneUtil.showConfirmationDialog("convert_to_data", Main.parent, msg, tr("Warning"),
                 JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE, JOptionPane.OK_OPTION)) {
Index: trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingCLI.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingCLI.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/mappaint/RenderingCLI.java	(revision 14119)
@@ -30,4 +30,5 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.preferences.JosmBaseDirectories;
+import org.openstreetmap.josm.data.preferences.JosmUrls;
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.data.projection.Projections;
@@ -423,4 +424,5 @@
         Config.setBaseDirectoriesProvider(JosmBaseDirectories.getInstance()); // for right-left-hand traffic cache file
         Config.setPreferencesInstance(new MemoryPreferences());
+        Config.setUrlsProvider(JosmUrls.getInstance());
         Config.getPref().putBoolean("mappaint.auto_reload_local_styles", false); // unnecessary to listen for external changes
         String projCode = Optional.ofNullable(argProjection).orElse("epsg:3857");
Index: trunk/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/oauth/OAuthAuthorizationWizard.java	(revision 14119)
@@ -46,5 +46,5 @@
 import org.openstreetmap.josm.gui.util.WindowGeometry;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
-import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -152,5 +152,5 @@
         lbl.setLabelFor(cbAuthorisationProcedure);
 
-        if (!OsmApi.DEFAULT_API_URL.equals(apiUrl)) {
+        if (!Config.getUrls().getDefaultOsmApiUrl().equals(apiUrl)) {
             gc.gridy = 3;
             gc.gridwidth = 2;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/imagery/ImageryPreference.java	(revision 14119)
@@ -72,4 +72,5 @@
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.gui.widgets.JosmEditorPane;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.ImageProvider;
@@ -378,5 +379,5 @@
 
             HtmlPanel help = new HtmlPanel(tr("New default entries can be added in the <a href=\"{0}\">Wiki</a>.",
-                Main.getJOSMWebsite()+"/wiki/Maps"));
+                Config.getUrls().getJOSMWebsite()+"/wiki/Maps"));
             help.enableClickableHyperlinks();
             add(help, GBC.eol().insets(10, 0, 0, 0).fill(GBC.HORIZONTAL));
Index: trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/map/MapPaintPreference.java	(revision 14119)
@@ -14,5 +14,4 @@
 import javax.swing.JPanel;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.preferences.sources.ExtendedSourceEntry;
 import org.openstreetmap.josm.data.preferences.sources.MapPaintPrefHelper;
@@ -86,5 +85,5 @@
 
         MapPaintSourceEditor() {
-            super(SourceType.MAP_PAINT_STYLE, Main.getJOSMWebsite()+"/styles", styleSourceProviders, true);
+            super(SourceType.MAP_PAINT_STYLE, Config.getUrls().getJOSMWebsite()+"/styles", styleSourceProviders, true);
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/map/TaggingPresetPreference.java	(revision 14119)
@@ -187,5 +187,5 @@
 
         TaggingPresetSourceEditor() {
-            super(SourceType.TAGGING_PRESET, Main.getJOSMWebsite()+"/presets", presetSourceProviders, true);
+            super(SourceType.TAGGING_PRESET, Config.getUrls().getJOSMWebsite()+"/presets", presetSourceProviders, true);
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/server/OsmApiUrlInputPanel.java	(revision 14119)
@@ -72,5 +72,6 @@
 
     protected JComponent buildDefaultServerUrlPanel() {
-        cbUseDefaultServerUrl = new JCheckBox(tr("<html>Use the default OSM server URL (<strong>{0}</strong>)</html>", OsmApi.DEFAULT_API_URL));
+        cbUseDefaultServerUrl = new JCheckBox(
+                tr("<html>Use the default OSM server URL (<strong>{0}</strong>)</html>", Config.getUrls().getDefaultOsmApiUrl()));
         cbUseDefaultServerUrl.addItemListener(new UseDefaultServerUrlChangeHandler());
         cbUseDefaultServerUrl.setFont(cbUseDefaultServerUrl.getFont().deriveFont(Font.PLAIN));
@@ -128,7 +129,7 @@
         String url = OsmApi.getOsmApi().getServerUrl();
         tfOsmServerUrl.setPossibleItems(SERVER_URL_HISTORY.get());
-        if (OsmApi.DEFAULT_API_URL.equals(url.trim())) {
+        if (Config.getUrls().getDefaultOsmApiUrl().equals(url.trim())) {
             cbUseDefaultServerUrl.setSelected(true);
-            propagator.propagate(OsmApi.DEFAULT_API_URL);
+            propagator.propagate(Config.getUrls().getDefaultOsmApiUrl());
         } else {
             cbUseDefaultServerUrl.setSelected(false);
@@ -144,5 +145,5 @@
         String oldUrl = OsmApi.getOsmApi().getServerUrl();
         String hmiUrl = getStrippedApiUrl();
-        if (cbUseDefaultServerUrl.isSelected() || OsmApi.DEFAULT_API_URL.equals(hmiUrl)) {
+        if (cbUseDefaultServerUrl.isSelected() || Config.getUrls().getDefaultOsmApiUrl().equals(hmiUrl)) {
             Config.getPref().put("osm-server.url", null);
         } else {
@@ -278,5 +279,5 @@
             case ItemEvent.SELECTED:
                 setApiUrlInputEnabled(false);
-                propagator.propagate(OsmApi.DEFAULT_API_URL);
+                propagator.propagate(Config.getUrls().getDefaultOsmApiUrl());
                 break;
             case ItemEvent.DESELECTED:
Index: trunk/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorTagCheckerRulesPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorTagCheckerRulesPreference.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/validator/ValidatorTagCheckerRulesPreference.java	(revision 14119)
@@ -10,5 +10,4 @@
 import java.util.List;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.preferences.sources.ExtendedSourceEntry;
 import org.openstreetmap.josm.data.preferences.sources.SourceEntry;
@@ -25,4 +24,5 @@
 import org.openstreetmap.josm.gui.preferences.TabPreferenceSetting;
 import org.openstreetmap.josm.gui.preferences.map.MapPaintPreference;
+import org.openstreetmap.josm.spi.preferences.Config;
 
 /**
@@ -58,5 +58,5 @@
 
         TagCheckerRulesSourceEditor() {
-            super(SourceType.TAGCHECKER_RULE, Main.getJOSMWebsite()+"/rules", ruleSourceProviders, false);
+            super(SourceType.TAGCHECKER_RULE, Config.getUrls().getJOSMWebsite()+"/rules", ruleSourceProviders, false);
         }
 
Index: trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/gui/tagging/presets/TaggingPresetReader.java	(revision 14119)
@@ -43,4 +43,5 @@
 import org.openstreetmap.josm.io.CachedFile;
 import org.openstreetmap.josm.io.UTFInputStreamReader;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.I18n;
 import org.openstreetmap.josm.tools.Logging;
@@ -178,5 +179,5 @@
 
         if (validate) {
-            parser.startWithValidation(in, Main.getXMLBase()+"/tagging-preset-1.0", "resource://data/tagging-preset.xsd");
+            parser.startWithValidation(in, Config.getUrls().getXMLBase()+"/tagging-preset-1.0", "resource://data/tagging-preset.xsd");
         } else {
             parser.start(in);
Index: trunk/src/org/openstreetmap/josm/io/AbstractReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/AbstractReader.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/io/AbstractReader.java	(revision 14119)
@@ -62,5 +62,5 @@
      * @param pp postprocessor
      * @see #deregisterPostprocessor
-     * @since xxx (moved from OsmReader)
+     * @since 14119 (moved from OsmReader)
      */
     public static void registerPostprocessor(OsmServerReadPostprocessor pp) {
@@ -75,5 +75,5 @@
      * @param pp postprocessor
      * @see #registerPostprocessor
-     * @since xxx (moved from OsmReader)
+     * @since 14119 (moved from OsmReader)
      */
     public static void deregisterPostprocessor(OsmServerReadPostprocessor pp) {
Index: trunk/src/org/openstreetmap/josm/io/CachedFile.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 14119)
@@ -541,5 +541,5 @@
 
     private static void checkOfflineAccess(String urlString) {
-        OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlString, Main.getJOSMWebsite());
+        OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlString, Config.getUrls().getJOSMWebsite());
         OnlineResource.OSM_API.checkOfflineAccess(urlString, OsmApi.getOsmApi().getServerUrl());
     }
Index: trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 14119)
@@ -37,4 +37,5 @@
 import org.openstreetmap.josm.io.auth.CredentialsManager;
 import org.openstreetmap.josm.spi.preferences.Config;
+import org.openstreetmap.josm.spi.preferences.IUrls;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.HttpClient;
@@ -73,6 +74,8 @@
     /**
      * Default URL of the standard OSM API.
+     * @deprecated Use {@link IUrls#getDefaultOsmApiUrl}
      * @since 5422
      */
+    @Deprecated
     public static final String DEFAULT_API_URL = "https://api.openstreetmap.org/api";
 
@@ -136,5 +139,5 @@
 
     private static String getServerUrlFromPref() {
-        return Config.getPref().get("osm-server.url", DEFAULT_API_URL);
+        return Config.getPref().get("osm-server.url", Config.getUrls().getDefaultOsmApiUrl());
     }
 
Index: trunk/src/org/openstreetmap/josm/io/OsmServerReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/io/OsmServerReader.java	(revision 14119)
@@ -14,5 +14,4 @@
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.gpx.GpxData;
 import org.openstreetmap.josm.data.notes.Note;
@@ -21,4 +20,5 @@
 import org.openstreetmap.josm.io.auth.CredentialsAgentException;
 import org.openstreetmap.josm.io.auth.CredentialsManager;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.HttpClient;
 import org.openstreetmap.josm.tools.Logging;
@@ -155,5 +155,5 @@
             boolean uncompressAccordingToContentDisposition, String httpMethod, byte[] requestBody) throws OsmTransferException {
         try {
-            OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlStr, Main.getJOSMWebsite());
+            OnlineResource.JOSM_WEBSITE.checkOfflineAccess(urlStr, Config.getUrls().getJOSMWebsite());
             OnlineResource.OSM_API.checkOfflineAccess(urlStr, OsmApi.getOsmApi().getServerUrl());
 
Index: trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/ImportHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/ImportHandler.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/io/remotecontrol/handler/ImportHandler.java	(revision 14119)
@@ -10,5 +10,4 @@
 import java.util.Set;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
 import org.openstreetmap.josm.actions.downloadtasks.DownloadTask;
@@ -75,5 +74,5 @@
     public String[] getUsageExamples() {
         return new String[] {"/import?url=" + Utils.encodeUrl(
-                Main.getJOSMWebsite()+"/browser/josm/trunk/data_nodist/direction-arrows.osm?format=txt")};
+                Config.getUrls().getJOSMWebsite()+"/browser/josm/trunk/data_nodist/direction-arrows.osm?format=txt")};
     }
 
Index: trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 14119)
@@ -536,5 +536,5 @@
             for (String updateSite : Main.pref.getPluginSites()) {
                 try {
-                    OnlineResource.JOSM_WEBSITE.checkOfflineAccess(updateSite, Main.getJOSMWebsite());
+                    OnlineResource.JOSM_WEBSITE.checkOfflineAccess(updateSite, Config.getUrls().getJOSMWebsite());
                 } catch (OfflineAccessException e) {
                     Logging.trace(e);
Index: trunk/src/org/openstreetmap/josm/spi/preferences/Config.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/Config.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/Config.java	(revision 14119)
@@ -12,4 +12,5 @@
     private static IPreferences preferences;
     private static IBaseDirectories baseDirectories;
+    private static IUrls urls;
 
     private Config() {
@@ -36,4 +37,13 @@
 
     /**
+     * Get class that provides the value of certain URLs
+     * @return the global {@link IUrls} instance
+     * @since 14119
+     */
+    public static IUrls getUrls() {
+        return urls;
+    }
+
+    /**
      * Install the global preference instance.
      * @param preferences the global preference instance to set (must not be null)
@@ -53,3 +63,12 @@
         Config.baseDirectories = Objects.requireNonNull(baseDirectories, "baseDirectories");
     }
+
+    /**
+     * Install the global URLs provider.
+     * @param urls the global URLs provider instance to set (must not be null)
+     * @since xx
+     */
+    public static void setUrlsProvider(IUrls urls) {
+        Config.urls = Objects.requireNonNull(urls, "urls");
+    }
 }
Index: trunk/src/org/openstreetmap/josm/spi/preferences/IUrls.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/IUrls.java	(revision 14119)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/IUrls.java	(revision 14119)
@@ -0,0 +1,51 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+/**
+ * Interface for a provider of certain URLs.
+ * @since 14119
+ */
+public interface IUrls {
+
+    /**
+     * Returns the OSM website URL depending on the selected OSM API.
+     * @return the OSM website URL depending on the selected OSM API
+     */
+    String getOSMWebsiteDependingOnSelectedApi();
+
+    /**
+     * Replies the base URL for browsing information about a primitive.
+     * @return the base URL, i.e. https://www.openstreetmap.org
+     */
+    String getBaseBrowseUrl();
+
+    /**
+     * Replies the base URL for browsing information about a user.
+     * @return the base URL, i.e. https://www.openstreetmap.org/user
+     */
+    String getBaseUserUrl();
+
+    /**
+     * Returns the JOSM website URL.
+     * @return the josm website URL
+     */
+    String getJOSMWebsite();
+
+    /**
+     * Returns the JOSM XML URL.
+     * @return the JOSM XML URL
+     */
+    String getXMLBase();
+
+    /**
+     * Returns the OSM website URL.
+     * @return the OSM website URL
+     */
+    String getOSMWebsite();
+
+    /**
+     * Returns the default OSM API URL.
+     * @return the default OSM API URL
+     */
+    String getDefaultOsmApiUrl();
+}
Index: trunk/src/org/openstreetmap/josm/tools/OsmUrlToBounds.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/OsmUrlToBounds.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/tools/OsmUrlToBounds.java	(revision 14119)
@@ -10,5 +10,4 @@
 import java.util.function.Supplier;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -17,4 +16,5 @@
 import org.openstreetmap.josm.data.projection.Projection;
 import org.openstreetmap.josm.data.projection.Projections;
+import org.openstreetmap.josm.spi.preferences.Config;
 
 /**
@@ -290,5 +290,5 @@
         double lon = Math.round(dlon * decimals);
         lon /= decimals;
-        return Main.getOSMWebsite() + "/#map="+zoom+'/'+lat+'/'+lon;
+        return Config.getUrls().getOSMWebsite() + "/#map="+zoom+'/'+lat+'/'+lon;
     }
 }
Index: trunk/src/org/openstreetmap/josm/tools/WikiReader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/WikiReader.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/tools/WikiReader.java	(revision 14119)
@@ -6,5 +6,4 @@
 import java.net.URL;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.LanguageInfo.LocaleType;
@@ -31,5 +30,5 @@
      */
     public WikiReader() {
-        this(Config.getPref().get("help.baseurl", Main.getJOSMWebsite()));
+        this(Config.getPref().get("help.baseurl", Config.getUrls().getJOSMWebsite()));
     }
 
Index: trunk/src/org/openstreetmap/josm/tools/bugreport/BugReportSender.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/bugreport/BugReportSender.java	(revision 14118)
+++ trunk/src/org/openstreetmap/josm/tools/bugreport/BugReportSender.java	(revision 14119)
@@ -16,5 +16,5 @@
 import javax.xml.xpath.XPathFactory;
 
-import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.HttpClient;
 import org.openstreetmap.josm.tools.HttpClient.Response;
@@ -136,5 +136,5 @@
 
     private static String getJOSMTicketURL() {
-        return Main.getJOSMWebsite() + "/josmticket";
+        return Config.getUrls().getJOSMWebsite() + "/josmticket";
     }
 
