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

Last change on this file since 1473 was 1473, checked in by stoecker, 15 years ago

fix #2252 - warning/exception on startup without prefs file

  • Property svn:eol-style set to native
File size: 19.2 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 Properties sysProp = System.getProperties();
525 if (getBoolean(ProxyPreferences.PROXY_ENABLE)) {
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 }/* else {
534 sysProp.put("proxySet", "false");
535 sysProp.remove("http.proxyHost");
536 sysProp.remove("proxyPort");
537 sysProp.remove("proxyUser");
538 sysProp.remove("proxyPassword");
539 }*/
540 System.setProperties(sysProp);
541 }
542}
Note: See TracBrowser for help on using the repository browser.