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