001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.preferences;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005import static org.openstreetmap.josm.tools.Utils.getSystemProperty;
006
007import java.awt.GraphicsEnvironment;
008import java.io.File;
009
010import javax.swing.JOptionPane;
011
012import org.openstreetmap.josm.gui.MainApplication;
013import org.openstreetmap.josm.spi.preferences.Config;
014import org.openstreetmap.josm.spi.preferences.IBaseDirectories;
015import org.openstreetmap.josm.tools.Logging;
016import org.openstreetmap.josm.tools.PlatformManager;
017
018/**
019 * Class provides base directory locations for JOSM.
020 * @since 13021
021 */
022public final class JosmBaseDirectories implements IBaseDirectories {
023
024    private JosmBaseDirectories() {
025        // hide constructor
026    }
027
028    private static class InstanceHolder {
029        static final JosmBaseDirectories INSTANCE = new JosmBaseDirectories();
030    }
031
032    /**
033     * Returns the unique instance.
034     * @return the unique instance
035     */
036    public static JosmBaseDirectories getInstance() {
037        return InstanceHolder.INSTANCE;
038    }
039
040    /**
041     * Internal storage for the preference directory.
042     */
043    private File preferencesDir;
044
045    /**
046     * Internal storage for the cache directory.
047     */
048    private File cacheDir;
049
050    /**
051     * Internal storage for the user data directory.
052     */
053    private File userdataDir;
054
055    @Override
056    public File getPreferencesDirectory(boolean createIfMissing) {
057        if (preferencesDir == null) {
058            String path = getSystemProperty("josm.pref");
059            if (path != null) {
060                preferencesDir = new File(path).getAbsoluteFile();
061            } else {
062                path = getSystemProperty("josm.home");
063                if (path != null) {
064                    preferencesDir = new File(path).getAbsoluteFile();
065                } else {
066                    preferencesDir = PlatformManager.getPlatform().getDefaultPrefDirectory();
067                }
068            }
069        }
070        try {
071            if (createIfMissing && !preferencesDir.exists() && !preferencesDir.mkdirs()) {
072                Logging.warn(tr("Failed to create missing preferences directory: {0}", preferencesDir.getAbsoluteFile()));
073                if (!GraphicsEnvironment.isHeadless()) {
074                    JOptionPane.showMessageDialog(
075                            MainApplication.getMainFrame(),
076                            tr("<html>Failed to create missing preferences directory: {0}</html>", preferencesDir.getAbsoluteFile()),
077                            tr("Error"),
078                            JOptionPane.ERROR_MESSAGE
079                    );
080                }
081            }
082        } catch (SecurityException e) {
083            Logging.log(Logging.LEVEL_ERROR, "Unable to check if preferences dir must be created", e);
084        }
085        return preferencesDir;
086    }
087
088    @Override
089    public File getUserDataDirectory(boolean createIfMissing) {
090        if (userdataDir == null) {
091            String path = getSystemProperty("josm.userdata");
092            if (path != null) {
093                userdataDir = new File(path).getAbsoluteFile();
094            } else {
095                path = getSystemProperty("josm.home");
096                if (path != null) {
097                    userdataDir = new File(path).getAbsoluteFile();
098                } else {
099                    userdataDir = PlatformManager.getPlatform().getDefaultUserDataDirectory();
100                }
101            }
102        }
103        try {
104            if (createIfMissing && !userdataDir.exists() && !userdataDir.mkdirs()) {
105                Logging.warn(tr("Failed to create missing user data directory: {0}", userdataDir.getAbsoluteFile()));
106                if (!GraphicsEnvironment.isHeadless()) {
107                    JOptionPane.showMessageDialog(
108                            MainApplication.getMainFrame(),
109                            tr("<html>Failed to create missing user data directory: {0}</html>", userdataDir.getAbsoluteFile()),
110                            tr("Error"),
111                            JOptionPane.ERROR_MESSAGE
112                    );
113                }
114            }
115        } catch (SecurityException e) {
116            Logging.log(Logging.LEVEL_ERROR, "Unable to check if user data dir must be created", e);
117        }
118        return userdataDir;
119    }
120
121    @Override
122    public File getCacheDirectory(boolean createIfMissing) {
123        if (cacheDir == null) {
124            String path = getSystemProperty("josm.cache");
125            if (path != null) {
126                cacheDir = new File(path).getAbsoluteFile();
127            } else {
128                path = getSystemProperty("josm.home");
129                if (path != null) {
130                    cacheDir = new File(path, "cache");
131                } else {
132                    path = Config.getPref().get("cache.folder", null);
133                    if (path != null) {
134                        cacheDir = new File(path).getAbsoluteFile();
135                    } else {
136                        cacheDir = PlatformManager.getPlatform().getDefaultCacheDirectory();
137                    }
138                }
139            }
140        }
141        try {
142            if (createIfMissing && !cacheDir.exists() && !cacheDir.mkdirs()) {
143                Logging.warn(tr("Failed to create missing cache directory: {0}", cacheDir.getAbsoluteFile()));
144                if (!GraphicsEnvironment.isHeadless()) {
145                    JOptionPane.showMessageDialog(
146                            MainApplication.getMainFrame(),
147                            tr("<html>Failed to create missing cache directory: {0}</html>", cacheDir.getAbsoluteFile()),
148                            tr("Error"),
149                            JOptionPane.ERROR_MESSAGE
150                    );
151                }
152            }
153        } catch (SecurityException e) {
154            Logging.log(Logging.LEVEL_ERROR, "Unable to check if cache dir must be created", e);
155        }
156        return cacheDir;
157    }
158
159    /**
160     * Clears any previously calculated values used for {@link #getPreferencesDirectory(boolean)},
161     * {@link #getCacheDirectory(boolean)} or {@link #getUserDataDirectory(boolean)}. Useful for tests.
162     * @since 14052
163     */
164    public void clearMemos() {
165        this.preferencesDir = null;
166        this.cacheDir = null;
167        this.userdataDir = null;
168    }
169}