Index: trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 12855)
@@ -38,4 +38,5 @@
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.plugins.PluginHandler;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.PlatformHookUnixoid;
@@ -230,9 +231,9 @@
         final String propJavaHome = System.getProperty("java.home");
         final String propJavaHomeAlt = "<java.home>";
-        final String prefDir = Main.pref.getPreferencesDirectory().toString();
+        final String prefDir = Config.getDirs().getPreferencesDirectory().toString();
         final String prefDirAlt = "<josm.pref>";
-        final String userDataDir = Main.pref.getUserDataDirectory().toString();
+        final String userDataDir = Config.getDirs().getUserDataDirectory().toString();
         final String userDataDirAlt = "<josm.userdata>";
-        final String userCacheDir = Main.pref.getCacheDirectory().toString();
+        final String userCacheDir = Config.getDirs().getCacheDirectory().toString();
         final String userCacheDirAlt = "<josm.cache>";
         final String userHomeDir = System.getProperty("user.home");
Index: trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 12855)
@@ -44,5 +44,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.spi.preferences.AbstractPreferences;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.data.preferences.ColorProperty;
@@ -62,4 +61,6 @@
 import org.openstreetmap.josm.io.OfflineAccessException;
 import org.openstreetmap.josm.io.OnlineResource;
+import org.openstreetmap.josm.spi.preferences.AbstractPreferences;
+import org.openstreetmap.josm.spi.preferences.IBaseDirectories;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 import org.openstreetmap.josm.tools.ColorHelper;
@@ -92,5 +93,5 @@
  * @since 74
  */
-public class Preferences extends AbstractPreferences {
+public class Preferences extends AbstractPreferences implements IBaseDirectories {
 
     private static final String COLOR_PREFIX = "color.";
@@ -331,4 +332,5 @@
      * @since 7834
      */
+    @Override
     public File getPreferencesDirectory() {
         if (preferencesDir != null)
@@ -355,4 +357,5 @@
      * @since 7834
      */
+    @Override
     public File getUserDataDirectory() {
         if (userdataDir != null)
@@ -404,4 +407,5 @@
      * @return the cache directory
      */
+    @Override
     public File getCacheDirectory() {
         if (cacheDir != null)
Index: trunk/src/org/openstreetmap/josm/data/cache/JCSCacheManager.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/cache/JCSCacheManager.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/data/cache/JCSCacheManager.java	(revision 12855)
@@ -27,7 +27,7 @@
 import org.apache.commons.jcs.engine.control.CompositeCacheManager;
 import org.apache.commons.jcs.utils.serialization.StandardSerializer;
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.data.preferences.IntegerProperty;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Logging;
 import org.openstreetmap.josm.tools.Utils;
@@ -101,5 +101,5 @@
     @SuppressWarnings("resource")
     private static void initialize() throws IOException {
-        File cacheDir = new File(Main.pref.getCacheDirectory(), "jcs");
+        File cacheDir = new File(Config.getDirs().getCacheDirectory(), "jcs");
 
         if (!cacheDir.exists() && !cacheDir.mkdirs())
Index: trunk/src/org/openstreetmap/josm/data/imagery/CachedTileLoaderFactory.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/imagery/CachedTileLoaderFactory.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/data/imagery/CachedTileLoaderFactory.java	(revision 12855)
@@ -11,5 +11,4 @@
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Version;
 import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
@@ -57,5 +56,5 @@
         String defPath = null;
         try {
-            defPath = new File(Main.pref.getCacheDirectory(), "tiles").getAbsolutePath();
+            defPath = new File(Config.getDirs().getCacheDirectory(), "tiles").getAbsolutePath();
         } catch (SecurityException e) {
             Logging.warn(e);
Index: trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/data/validation/OsmValidator.java	(revision 12855)
@@ -176,5 +176,5 @@
      */
     public static String getValidatorDir() {
-        return new File(Main.pref.getUserDataDirectory(), "validator").getAbsolutePath();
+        return new File(Config.getDirs().getUserDataDirectory(), "validator").getAbsolutePath();
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 12855)
@@ -916,4 +916,5 @@
         Main.pref.init(args.hasOption(Option.RESET_PREFERENCES));
         Config.setPreferencesInstance(Main.pref);
+        Config.setBaseDirectoriesProvider(Main.pref);
 
         args.getPreferencesToSet().forEach(Main.pref::put);
Index: trunk/src/org/openstreetmap/josm/gui/io/CustomConfigurator.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/io/CustomConfigurator.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/gui/io/CustomConfigurator.java	(revision 12855)
@@ -425,7 +425,7 @@
         String dir;
         if ("prefs".equals(base) || base.isEmpty()) {
-            dir = Main.pref.getPreferencesDirectory().getAbsolutePath();
+            dir = Config.getDirs().getPreferencesDirectory().getAbsolutePath();
         } else if ("cache".equals(base)) {
-            dir = Main.pref.getCacheDirectory().getAbsolutePath();
+            dir = Config.getDirs().getCacheDirectory().getAbsolutePath();
         } else if ("plugins".equals(base)) {
             dir = Main.pref.getPluginsDirectory().getAbsolutePath();
@@ -477,5 +477,5 @@
                 engine.eval("API={}; API.pref={}; API.fragments={};");
 
-                engine.eval("homeDir='"+normalizeDirName(Main.pref.getPreferencesDirectory().getAbsolutePath()) +"';");
+                engine.eval("homeDir='"+normalizeDirName(Config.getDirs().getPreferencesDirectory().getAbsolutePath()) +"';");
                 engine.eval("josmVersion="+Version.getInstance().getVersion()+';');
                 String className = CustomConfigurator.class.getName();
Index: trunk/src/org/openstreetmap/josm/gui/layer/AutosaveTask.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/AutosaveTask.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/gui/layer/AutosaveTask.java	(revision 12855)
@@ -29,5 +29,4 @@
 import java.util.regex.Pattern;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.OpenFileAction.OpenFileTask;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -117,6 +116,6 @@
     private final Deque<File> deletedLayers = new LinkedList<>();
 
-    private final File autosaveDir = new File(Main.pref.getUserDataDirectory(), AUTOSAVE_DIR);
-    private final File deletedLayersDir = new File(Main.pref.getUserDataDirectory(), DELETED_LAYERS_DIR);
+    private final File autosaveDir = new File(Config.getDirs().getUserDataDirectory(), AUTOSAVE_DIR);
+    private final File deletedLayersDir = new File(Config.getDirs().getUserDataDirectory(), DELETED_LAYERS_DIR);
 
     /**
Index: trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ThumbsLoader.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ThumbsLoader.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/gui/layer/geoimage/ThumbsLoader.java	(revision 12855)
@@ -18,5 +18,4 @@
 
 import org.apache.commons.jcs.access.behavior.ICacheAccess;
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
 import org.openstreetmap.josm.data.cache.JCSCacheManager;
@@ -70,5 +69,5 @@
             try {
                 cache = JCSCacheManager.getCache("geoimage-thumbnails", 0, 120,
-                        Main.pref.getCacheDirectory().getPath() + File.separator + "geoimage-thumbnails");
+                        Config.getDirs().getCacheDirectory().getPath() + File.separator + "geoimage-thumbnails");
             } catch (IOException e) {
                 Logging.warn("Failed to initialize cache for geoimage-thumbnails");
Index: trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/advanced/AdvancedPreference.java	(revision 12855)
@@ -51,4 +51,5 @@
 import org.openstreetmap.josm.gui.widgets.AbstractFileChooser;
 import org.openstreetmap.josm.gui.widgets.JosmTextField;
+import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.Logging;
@@ -369,5 +370,5 @@
                     }
                 }
-                files = Main.pref.getPreferencesDirectory().listFiles();
+                files = Config.getDirs().getPreferencesDirectory().listFiles();
                 if (files != null) {
                     for (File f: files) {
Index: trunk/src/org/openstreetmap/josm/io/CacheCustomContent.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/CacheCustomContent.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/io/CacheCustomContent.java	(revision 12855)
@@ -11,5 +11,4 @@
 import java.util.concurrent.TimeUnit;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.spi.preferences.Config;
 import org.openstreetmap.josm.tools.Logging;
@@ -77,5 +76,5 @@
         this.ident = ident;
         this.updateInterval = updateInterval;
-        this.path = new File(Main.pref.getCacheDirectory(), ident);
+        this.path = new File(Config.getDirs().getCacheDirectory(), ident);
     }
 
Index: trunk/src/org/openstreetmap/josm/io/CachedFile.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/io/CachedFile.java	(revision 12855)
@@ -277,5 +277,5 @@
                 return null;
             } else if (name.startsWith("josmdir://")) {
-                cacheFile = new File(Main.pref.getUserDataDirectory(), name.substring("josmdir://".length()));
+                cacheFile = new File(Config.getDirs().getUserDataDirectory(), name.substring("josmdir://".length()));
             } else if (name.startsWith("josmplugindir://")) {
                 cacheFile = new File(Main.pref.getPluginsDirectory(), name.substring("josmplugindir://".length()));
@@ -448,5 +448,5 @@
         }
         if (destDir == null) {
-            destDir = Main.pref.getCacheDirectory().getPath();
+            destDir = Config.getDirs().getCacheDirectory().getPath();
         }
 
Index: trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/io/remotecontrol/RemoteControl.java	(revision 12855)
@@ -8,5 +8,4 @@
 import java.net.UnknownHostException;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.preferences.BooleanProperty;
 import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler;
@@ -96,5 +95,5 @@
      */
     public static String getRemoteControlDir() {
-        return new File(Main.pref.getUserDataDirectory(), "remotecontrol").getAbsolutePath();
+        return new File(Config.getDirs().getUserDataDirectory(), "remotecontrol").getAbsolutePath();
     }
 
Index: trunk/src/org/openstreetmap/josm/spi/preferences/Config.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/Config.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/Config.java	(revision 12855)
@@ -5,5 +5,5 @@
 
 /**
- * Class to hold the global preferences object.
+ * Class to hold the global preferences object and the provider of base directories.
  * @since 12847
  */
@@ -11,4 +11,5 @@
 
     private static IPreferences preferences;
+    private static IBaseDirectories baseDirectories;
 
     private Config() {
@@ -26,9 +27,29 @@
 
     /**
+     * Get class that provides the location of certain base directories
+     * @return the global {@link IBaseDirectories} instance
+     * @since 12855
+     */
+    public static IBaseDirectories getDirs() {
+        return baseDirectories;
+    }
+
+    /**
      * Install the global preference instance.
      * @param preferences the global preference instance to set (must not be null)
+     * @since 12847
      */
     public static void setPreferencesInstance(IPreferences preferences) {
         Config.preferences = Objects.requireNonNull(preferences, "preferences");
     }
+
+    /**
+     * Install the global base directories provider.
+     * @param baseDirectories the global base directories provider instance to set
+     * (must not be null)
+     * @since 12855
+     */
+    public static void setBaseDirectoriesProvider(IBaseDirectories baseDirectories) {
+        Config.baseDirectories = Objects.requireNonNull(baseDirectories, "baseDirectories");
+    }
 }
Index: trunk/src/org/openstreetmap/josm/spi/preferences/IBaseDirectories.java
===================================================================
--- trunk/src/org/openstreetmap/josm/spi/preferences/IBaseDirectories.java	(revision 12855)
+++ trunk/src/org/openstreetmap/josm/spi/preferences/IBaseDirectories.java	(revision 12855)
@@ -0,0 +1,33 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.spi.preferences;
+
+import java.io.File;
+
+/**
+ * Interface for a provider of certain base directory locations.
+ * <p>
+ * Depending on the OS and preferred layout, some directories may coincide.
+ * @since 12855
+ */
+public interface IBaseDirectories {
+
+    /**
+     * Get the directory where user-specific configuration and preferences
+     * should be stored.
+     * @return the preferences directory
+     */
+    File getPreferencesDirectory();
+
+    /**
+     * Get the directory where user-specific data files should be stored.
+     * @return the user data directory
+     */
+    File getUserDataDirectory();
+
+    /**
+     * Get the directory where user-specific cached content (non-essential data)
+     * should be stored.
+     * @return the cache directory
+     */
+    File getCacheDirectory();
+}
Index: trunk/src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 12855)
@@ -927,5 +927,6 @@
      */
     private static ImageResource getIfAvailableHttp(String url, ImageType type) {
-        try (CachedFile cf = new CachedFile(url).setDestDir(new File(Main.pref.getCacheDirectory(), "images").getPath());
+        try (CachedFile cf = new CachedFile(url).setDestDir(
+                new File(Config.getDirs().getCacheDirectory(), "images").getPath());
              InputStream is = cf.getInputStream()) {
             switch (type) {
@@ -1172,6 +1173,6 @@
         }
         // Try user-data directory
-        if (Main.pref != null) {
-            String dir = new File(Main.pref.getUserDataDirectory(), "images").getAbsolutePath();
+        if (Config.getDirs() != null) {
+            String dir = new File(Config.getDirs().getUserDataDirectory(), "images").getAbsolutePath();
             try {
                 u = getImageUrl(dir, imageName, additionalClassLoaders);
@@ -1246,5 +1247,6 @@
             parser.setEntityResolver((publicId, systemId) -> new InputSource(new ByteArrayInputStream(new byte[0])));
 
-            try (CachedFile cf = new CachedFile(base + fn).setDestDir(new File(Main.pref.getUserDataDirectory(), "images").getPath());
+            try (CachedFile cf = new CachedFile(base + fn).setDestDir(
+                        new File(Config.getDirs().getUserDataDirectory(), "images").getPath());
                  InputStream is = cf.getInputStream()) {
                 parser.parse(new InputSource(is));
Index: trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/tools/PlatformHookWindows.java	(revision 12855)
@@ -477,5 +477,5 @@
     public File getDefaultUserDataDirectory() {
         // Use preferences directory by default
-        return Main.pref.getPreferencesDirectory();
+        return Config.getDirs().getPreferencesDirectory();
     }
 
@@ -522,5 +522,5 @@
             props.load(fis);
             byte[] content = Files.readAllBytes(templateFile);
-            File cachePath = Main.pref.getCacheDirectory();
+            File cachePath = Config.getDirs().getCacheDirectory();
             Path fontconfigFile = cachePath.toPath().resolve("fontconfig.properties");
             OutputStream os = Files.newOutputStream(fontconfigFile);
Index: trunk/src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java	(revision 12854)
+++ trunk/src/org/openstreetmap/josm/tools/RightAndLefthandTraffic.java	(revision 12855)
@@ -17,5 +17,4 @@
 import java.util.Set;
 
-import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.JoinAreasAction;
 import org.openstreetmap.josm.actions.JoinAreasAction.JoinAreasResult;
@@ -32,4 +31,5 @@
 import org.openstreetmap.josm.io.OsmWriter;
 import org.openstreetmap.josm.io.OsmWriterFactory;
+import org.openstreetmap.josm.spi.preferences.Config;
 
 /**
@@ -153,5 +153,5 @@
     private static void saveOptimizedBoundaries(Collection<Way> optimizedWays) {
         DataSet ds = optimizedWays.iterator().next().getDataSet();
-        File file = new File(Main.pref.getCacheDirectory(), "left-right-hand-traffic.osm");
+        File file = new File(Config.getDirs().getCacheDirectory(), "left-right-hand-traffic.osm");
         try (Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
              OsmWriter w = OsmWriterFactory.createOsmWriter(new PrintWriter(writer), false, ds.getVersion())
@@ -166,5 +166,5 @@
 
     private static Collection<Way> loadOptimizedBoundaries() {
-        try (InputStream is = new FileInputStream(new File(Main.pref.getCacheDirectory(), "left-right-hand-traffic.osm"))) {
+        try (InputStream is = new FileInputStream(new File(Config.getDirs().getCacheDirectory(), "left-right-hand-traffic.osm"))) {
            return OsmReader.parseDataSet(is, null).getWays();
         } catch (IllegalDataException | IOException ex) {
