source: josm/trunk/src/org/openstreetmap/josm/data/Preferences.java @ 1480

Last change on this file since 1480 was 1480, checked in by stoecker, 10 years ago

added user agent

  • Property svn:eol-style set to native
File size: 19.0 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.data;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.io.BufferedReader;
8import java.io.File;
9import java.io.FileReader;
10import java.io.FileWriter;
11import java.io.IOException;
12import java.io.PrintWriter;
13import java.util.ArrayList;
14import java.util.Arrays;
15import java.util.Collection;
16import java.util.Collections;
17import java.util.LinkedList;
18import java.util.Map;
19import java.util.Properties;
20import java.util.SortedMap;
21import java.util.TreeMap;
22import java.util.Map.Entry;
23import java.util.regex.Matcher;
24import java.util.regex.Pattern;
25
26import javax.swing.JOptionPane;
27
28import org.openstreetmap.josm.Main;
29import org.openstreetmap.josm.actions.AboutAction;
30import org.openstreetmap.josm.data.projection.Epsg4326;
31import org.openstreetmap.josm.gui.preferences.ProxyPreferences;
32import org.openstreetmap.josm.tools.ColorHelper;
33
34/**
35 * This class holds all preferences for JOSM.
36 *
37 * Other classes can register their beloved properties here. All properties will be
38 * saved upon set-access.
39 *
40 * @author imi
41 */
42public class Preferences {
43
44    /**
45    * Internal storage for the preferenced directory.
46    * Do not access this variable directly!
47    * @see #getPreferencesDirFile()
48    */
49    private File preferencesDirFile = null;
50
51    public static interface PreferenceChangedListener {
52        void preferenceChanged(String key, String newValue);
53    }
54
55    /**
56     * Class holding one bookmarkentry.
57     * @author imi
58     */
59    public static class Bookmark implements Comparable<Bookmark> {
60        public String name;
61        public double[] latlon = new double[4]; // minlat, minlon, maxlat, maxlon
62        @Override public String toString() {
63            return name;
64        }
65        public int compareTo(Bookmark b) {
66            return name.toLowerCase().compareTo(b.name.toLowerCase());
67        }
68    }
69
70    public final ArrayList<PreferenceChangedListener> listener = new ArrayList<PreferenceChangedListener>();
71
72    /**
73     * Map the property name to the property object.
74     */
75    protected final SortedMap<String, String> properties = new TreeMap<String, String>();
76    protected final SortedMap<String, String> defaults = new TreeMap<String, String>();
77
78    /**
79     * Override some values on read. This is intended to be used for technology previews
80     * where we want to temporarily modify things without changing the user's preferences
81     * file.
82     */
83    protected static final SortedMap<String, String> override = new TreeMap<String, String>();
84    static {
85        //override.put("osm-server.version", "0.5");
86        //override.put("osm-server.additional-versions", "");
87        //override.put("osm-server.url", "http://openstreetmap.gryph.de/api");
88        //override.put("plugins", null);
89    }
90
91    /**
92     * Return the location of the user defined preferences file
93     */
94    public String getPreferencesDir() {
95        final String path = getPreferencesDirFile().getPath();
96        if (path.endsWith(File.separator))
97            return path;
98        return path + File.separator;
99    }
100
101    public File getPreferencesDirFile() {
102        if (preferencesDirFile != null)
103            return preferencesDirFile;
104        String path;
105        path = System.getProperty("josm.home");
106        if (path != null) {
107            preferencesDirFile = new File(path);
108        } else {
109            path = System.getenv("APPDATA");
110            if (path != null) {
111                preferencesDirFile = new File(path, "JOSM");
112            } else {
113                preferencesDirFile = new File(System.getProperty("user.home"), ".josm");
114            }
115        }
116        return preferencesDirFile;
117    }
118
119    public File getPluginsDirFile() {
120        return new File(getPreferencesDirFile(), "plugins");
121    }
122
123    /**
124     * @return A list of all existing directories where resources could be stored.
125     */
126    public Collection<String> getAllPossiblePreferenceDirs() {
127        LinkedList<String> locations = new LinkedList<String>();
128        locations.add(Main.pref.getPreferencesDir());
129        String s;
130        if ((s = System.getenv("JOSM_RESOURCES")) != null) {
131            if (!s.endsWith(File.separator))
132                s = s + File.separator;
133            locations.add(s);
134        }
135        if ((s = System.getProperty("josm.resources")) != null) {
136            if (!s.endsWith(File.separator))
137                s = s + File.separator;
138            locations.add(s);
139        }
140        String appdata = System.getenv("APPDATA");
141        if (System.getenv("ALLUSERSPROFILE") != null && appdata != null
142                && appdata.lastIndexOf(File.separator) != -1) {
143            appdata = appdata.substring(appdata.lastIndexOf(File.separator));
144            locations.add(new File(new File(System.getenv("ALLUSERSPROFILE"),
145                    appdata), "JOSM").getPath());
146        }
147        locations.add("/usr/local/share/josm/");
148        locations.add("/usr/local/lib/josm/");
149        locations.add("/usr/share/josm/");
150        locations.add("/usr/lib/josm/");
151        return locations;
152    }
153
154    synchronized public boolean hasKey(final String key) {
155        return override.containsKey(key) ? override.get(key) != null : properties.containsKey(key);
156    }
157
158    synchronized public String get(final String key) {
159        putDefault(key, null);
160        if (override.containsKey(key))
161            return override.get(key);
162        if (!properties.containsKey(key))
163            return "";
164        return properties.get(key);
165    }
166
167    synchronized public String get(final String key, final String def) {
168        putDefault(key, def);
169        if (override.containsKey(key))
170            return override.get(key);
171        final String prop = properties.get(key);
172        if (prop == null || prop.equals(""))
173            return def;
174        return prop;
175    }
176
177    synchronized public Map<String, String> getAllPrefix(final String prefix) {
178        final Map<String,String> all = new TreeMap<String,String>();
179        for (final Entry<String,String> e : properties.entrySet())
180            if (e.getKey().startsWith(prefix))
181                all.put(e.getKey(), e.getValue());
182        for (final Entry<String,String> e : override.entrySet())
183            if (e.getKey().startsWith(prefix))
184                if (e.getValue() == null)
185                    all.remove(e.getKey());
186                else
187                    all.put(e.getKey(), e.getValue());
188        return all;
189    }
190
191    synchronized public TreeMap<String, String> getAllColors() {
192        final TreeMap<String,String> all = new TreeMap<String,String>();
193        for (final Entry<String,String> e : defaults.entrySet())
194            if (e.getKey().startsWith("color.") && e.getValue() != null)
195                all.put(e.getKey().substring(6), e.getValue());
196        for (final Entry<String,String> e : properties.entrySet())
197            if (e.getKey().startsWith("color."))
198                all.put(e.getKey().substring(6), e.getValue());
199        for (final Entry<String,String> e : override.entrySet())
200            if (e.getKey().startsWith("color."))
201                if (e.getValue() == null)
202                    all.remove(e.getKey().substring(6));
203                else
204                    all.put(e.getKey().substring(6), e.getValue());
205        return all;
206    }
207
208    synchronized public Map<String, String> getDefaults() {
209        return defaults;
210    }
211
212    synchronized public void putDefault(final String key, final String def) {
213        if(!defaults.containsKey(key) || defaults.get(key) == null)
214            defaults.put(key, def);
215        else if(def != null && !defaults.get(key).equals(def))
216            System.out.println("Defaults for " + key + " differ: " + def + " != " + defaults.get(key));
217    }
218
219    synchronized public boolean getBoolean(final String key) {
220        putDefault(key, null);
221        if (override.containsKey(key))
222            return override.get(key) == null ? false : Boolean.parseBoolean(override.get(key));
223        return properties.containsKey(key) ? Boolean.parseBoolean(properties.get(key)) : false;
224    }
225
226    synchronized public boolean getBoolean(final String key, final boolean def) {
227        putDefault(key, Boolean.toString(def));
228        if (override.containsKey(key))
229            return override.get(key) == null ? def : Boolean.parseBoolean(override.get(key));
230        return properties.containsKey(key) ? Boolean.parseBoolean(properties.get(key)) : def;
231    }
232
233    synchronized public boolean put(final String key, String value) {
234        String oldvalue = properties.get(key);
235        if(value != null && value.length() == 0)
236            value = null;
237        if(!((oldvalue == null && (value == null || value.equals(defaults.get(key))))
238        || (value != null && oldvalue != null && oldvalue.equals(value))))
239        {
240            if (value == null)
241                properties.remove(key);
242            else
243                properties.put(key, value);
244            save();
245            firePreferenceChanged(key, value);
246            return true;
247        }
248        return false;
249    }
250
251    synchronized public boolean put(final String key, final boolean value) {
252        return put(key, Boolean.toString(value));
253    }
254
255    synchronized public boolean putInteger(final String key, final Integer value) {
256        return put(key, Integer.toString(value));
257    }
258
259    synchronized public boolean putDouble(final String key, final Double value) {
260        return put(key, Double.toString(value));
261    }
262
263    private final void firePreferenceChanged(final String key, final String value) {
264        for (final PreferenceChangedListener l : listener)
265            l.preferenceChanged(key, value);
266    }
267
268    /**
269     * Called after every put. In case of a problem, do nothing but output the error
270     * in log.
271     */
272    public void save() {
273        /* currently unused, but may help to fix configuration issues in future */
274        properties.put("josm.version", AboutAction.getVersionString());
275        try {
276            setSystemProperties();
277            final PrintWriter out = new PrintWriter(new FileWriter(getPreferencesDir() + "preferences"), false);
278            for (final Entry<String, String> e : properties.entrySet()) {
279                String s = defaults.get(e.getKey());
280                /* don't save default values */
281                if(s == null || !s.equals(e.getValue()))
282                    out.println(e.getKey() + "=" + e.getValue());
283            }
284            out.close();
285        } catch (final IOException e) {
286            e.printStackTrace();
287            // do not message anything, since this can be called from strange
288            // places.
289        }
290    }
291
292    public void load() throws IOException {
293        properties.clear();
294        final BufferedReader in = new BufferedReader(new FileReader(getPreferencesDir()+"preferences"));
295        int lineNumber = 0;
296        ArrayList<Integer> errLines = new ArrayList<Integer>();
297        for (String line = in.readLine(); line != null; line = in.readLine(), lineNumber++) {
298            final int i = line.indexOf('=');
299            if (i == -1 || i == 0) {
300                errLines.add(lineNumber);
301                continue;
302            }
303            properties.put(line.substring(0,i), line.substring(i+1));
304        }
305        if (!errLines.isEmpty())
306            throw new IOException(tr("Malformed config file at lines {0}", errLines));
307        setSystemProperties();
308    }
309
310    public void init(Boolean reset)
311    {
312        // get the preferences.
313        File prefDir = getPreferencesDirFile();
314        if (prefDir.exists()) {
315            if(!prefDir.isDirectory()) {
316                JOptionPane.showMessageDialog(null, tr("Cannot open preferences directory: {0}",Main.pref.getPreferencesDir()));
317                return;
318            }
319        }
320        else
321            prefDir.mkdirs();
322
323        if (!new File(getPreferencesDir()+"preferences").exists())
324            resetToDefault();
325
326        try {
327            if (reset)
328                resetToDefault();
329            else
330                load();
331        } catch (final IOException e1) {
332            e1.printStackTrace();
333            String backup = getPreferencesDir() + "preferences.bak";
334            JOptionPane.showMessageDialog(null, tr("Preferences file had errors. Making backup of old one to {0}.", backup));
335            new File(getPreferencesDir() + "preferences").renameTo(new File(backup));
336            save();
337        }
338    }
339
340    public final void resetToDefault() {
341        properties.clear();
342        put("layerlist.visible", true);
343        put("propertiesdialog.visible", true);
344        put("selectionlist.visible", true);
345        put("commandstack.visible", true);
346        put("projection", Epsg4326.class.getName());
347        put("osm-server.url", "http://www.openstreetmap.org/api");
348        if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS") == -1) {
349            put("laf", "javax.swing.plaf.metal.MetalLookAndFeel");
350        } else {
351            put("laf", "com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
352        }
353        save();
354    }
355
356    public Collection<Bookmark> loadBookmarks() throws IOException {
357        File bookmarkFile = new File(getPreferencesDir()+"bookmarks");
358        if (!bookmarkFile.exists())
359            bookmarkFile.createNewFile();
360        BufferedReader in = new BufferedReader(new FileReader(bookmarkFile));
361
362        LinkedList<Bookmark> bookmarks = new LinkedList<Bookmark>();
363        // use pattern matches to scan text, as text may contain a "," itself
364        for (String line = in.readLine(); line != null; line = in.readLine()) {
365            Matcher m = Pattern.compile("^(.+),(-?\\d+.\\d+),(-?\\d+.\\d+),(-?\\d+.\\d+),(-?\\d+.\\d+)$").matcher(line);
366            if(m.matches())
367            {
368                Bookmark b = new Bookmark();
369                b.name = m.group(1);
370                for (int i = 0; i < b.latlon.length; ++i)
371                    b.latlon[i] = Double.parseDouble(m.group(i+2));
372                bookmarks.add(b);
373            }
374        }
375        in.close();
376        Collections.sort(bookmarks);
377        return bookmarks;
378    }
379
380    public void saveBookmarks(Collection<Bookmark> bookmarks) throws IOException {
381        File bookmarkFile = new File(Main.pref.getPreferencesDir()+"bookmarks");
382        if (!bookmarkFile.exists())
383            bookmarkFile.createNewFile();
384        PrintWriter out = new PrintWriter(new FileWriter(bookmarkFile));
385        for (Bookmark b : bookmarks) {
386            out.print(b.name+",");
387            for (int i = 0; i < b.latlon.length; ++i)
388                out.print(b.latlon[i]+(i<b.latlon.length-1?",":""));
389            out.println();
390        }
391        out.close();
392    }
393
394    /**
395     * Convenience method for accessing colour preferences.
396     *
397     * @param colName name of the colour
398     * @param def default value
399     * @return a Color object for the configured colour, or the default value if none configured.
400     */
401    synchronized public Color getColor(String colName, Color def) {
402        return getColor(colName, null, def);
403    }
404
405    /**
406     * Convenience method for accessing colour preferences.
407     *
408     * @param colName name of the colour
409     * @param specName name of the special colour settings
410     * @param def default value
411     * @return a Color object for the configured colour, or the default value if none configured.
412     */
413    synchronized public Color getColor(String colName, String specName, Color def) {
414        putDefault("color."+colName, ColorHelper.color2html(def));
415        String colStr = specName != null ? get("color."+specName) : "";
416        if(colStr.equals(""))
417            colStr = get("color."+colName);
418        return colStr.equals("") ? def : ColorHelper.html2color(colStr);
419    }
420
421    synchronized public Color getDefaultColor(String colName) {
422        String colStr = defaults.get("color."+colName);
423        return colStr.equals("") ? null : ColorHelper.html2color(colStr);
424    }
425
426    synchronized public boolean putColor(String colName, Color val) {
427        return put("color."+colName, val != null ? ColorHelper.color2html(val) : null);
428    }
429
430    synchronized public int getInteger(String key, int def) {
431        putDefault(key, Integer.toString(def));
432        String v = get(key);
433        if(null == v)
434            return def;
435
436        try {
437            return Integer.parseInt(v);
438        } catch(NumberFormatException e) {
439            // fall out
440        }
441        return def;
442    }
443
444    synchronized public long getLong(String key, long def) {
445        putDefault(key, Long.toString(def));
446        String v = get(key);
447        if(null == v)
448            return def;
449
450        try {
451            return Long.parseLong(v);
452        } catch(NumberFormatException e) {
453            // fall out
454        }
455        return def;
456    }
457
458    synchronized public double getDouble(String key, double def) {
459        putDefault(key, Double.toString(def));
460        String v = get(key);
461        if(null == v)
462            return def;
463
464        try {
465            return Double.parseDouble(v);
466        } catch(NumberFormatException e) {
467            // fall out
468        }
469        return def;
470    }
471
472    synchronized public double getDouble(String key, String def) {
473        putDefault(key, def);
474        String v = get(key);
475        if(v != null && v.length() != 0)
476            try { return Double.parseDouble(v); } catch(NumberFormatException e) {}
477        try { return Double.parseDouble(def); } catch(NumberFormatException e) {}
478        return 0.0;
479    }
480
481    synchronized public Collection<String> getCollection(String key, Collection<String> def) {
482        String s = get(key);
483        if(def != null)
484        {
485            String d = null;
486            for(String a : def)
487            {
488                if(d != null)
489                    d += ";" + a;
490                else
491                    d = a;
492            }
493            putDefault(key, d);
494        }
495        if(s != null && s.length() != 0)
496           return Arrays.asList(s.split(";"));
497        return def;
498    }
499    synchronized public void removeFromCollection(String key, String value) {
500        ArrayList<String> a = new ArrayList<String>(getCollection(key, null));
501        if(a != null)
502        {
503            a.remove(value);
504            putCollection(key, a);
505        }
506    }
507    synchronized public boolean putCollection(String key, Collection<String> val) {
508        String s = null;
509        if(val != null)
510        {
511            for(String a : val)
512            {
513                if(s != null)
514                    s += ";" + a;
515                else
516                    s = a;
517            }
518        }
519
520        return put(key, s);
521    }
522
523    private void setSystemProperties() {
524        if (getBoolean(ProxyPreferences.PROXY_ENABLE)) {
525            Properties sysProp = System.getProperties();
526            sysProp.put("proxySet", "true");
527            sysProp.put("http.proxyHost", get(ProxyPreferences.PROXY_HOST));
528            sysProp.put("proxyPort", get(ProxyPreferences.PROXY_PORT));
529            if (!getBoolean(ProxyPreferences.PROXY_ANONYMOUS)) {
530                sysProp.put("proxyUser", get(ProxyPreferences.PROXY_USER));
531                sysProp.put("proxyPassword", get(ProxyPreferences.PROXY_PASS));
532            }
533            System.setProperties(sysProp);
534        }
535        AboutAction.setUserAgent();
536    }
537}
Note: See TracBrowser for help on using the repository browser.