Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
ConfigurationHandler |
|
| 1.9722222222222223;1.972 |
1 | /* $Id: ConfigurationHandler.java 17819 2010-01-12 18:40:41Z linus $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009 Contributors - see below | |
4 | * All rights reserved. This program and the accompanying materials | |
5 | * are made available under the terms of the Eclipse Public License v1.0 | |
6 | * which accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * linus | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 1996-2007 The Regents of the University of California. All | |
17 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
18 | // software and its documentation without fee, and without a written | |
19 | // agreement is hereby granted, provided that the above copyright notice | |
20 | // and this paragraph appear in all copies. This software program and | |
21 | // documentation are copyrighted by The Regents of the University of | |
22 | // California. The software program and documentation are supplied "AS | |
23 | // IS", without any accompanying services from The Regents. The Regents | |
24 | // does not warrant that the operation of the program will be | |
25 | // uninterrupted or error-free. The end-user understands that the program | |
26 | // was developed for research purposes and is advised not to rely | |
27 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
28 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
29 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
30 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
31 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
32 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
33 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
34 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
35 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
36 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
37 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
38 | ||
39 | package org.argouml.configuration; | |
40 | ||
41 | import java.beans.PropertyChangeListener; | |
42 | import java.beans.PropertyChangeSupport; | |
43 | import java.io.File; | |
44 | import java.net.URL; | |
45 | ||
46 | import org.apache.log4j.Logger; | |
47 | ||
48 | /** | |
49 | * This class provides a user configuration based upon properties. | |
50 | * This provides an implementation-free interface to a configuration | |
51 | * repository. Any classes which need to implement a configuration | |
52 | * datastore must extend this class. | |
53 | * | |
54 | * All of the required behavioral logic for the configuration is | |
55 | * contained within this class, as public final methods. Any | |
56 | * storage-related logic must be handled by the extending class. | |
57 | * These methods are abstract. | |
58 | * | |
59 | * This class is intimately related to | |
60 | * {@link org.argouml.configuration.Configuration}. | |
61 | * | |
62 | * @author Thierry Lach | |
63 | * | |
64 | * @since 0.9.4 | |
65 | */ | |
66 | public abstract class ConfigurationHandler { | |
67 | ||
68 | /** | |
69 | * Internal storage for the <code>File</code> the configuration was | |
70 | * loaded from, otherwise null. | |
71 | */ | |
72 | private File loadedFromFile; | |
73 | ||
74 | /** | |
75 | * Internal storage for the <code>URL</code> the configuration was | |
76 | * loaded from, otherwise null. | |
77 | */ | |
78 | private URL loadedFromURL; | |
79 | ||
80 | /** | |
81 | * Internal flag indicating whether the configuration can be updated. | |
82 | */ | |
83 | private boolean changeable; | |
84 | ||
85 | /** | |
86 | * Internal flag indicating whether the configuration has been loaded. | |
87 | * Configuration rules allow a single load, whether manual or automatic. | |
88 | */ | |
89 | private boolean loaded; | |
90 | ||
91 | /** | |
92 | * Internal worker for property change. | |
93 | */ | |
94 | private static PropertyChangeSupport pcl; | |
95 | ||
96 | /** | |
97 | * Logger. | |
98 | */ | |
99 | 900 | private static final Logger LOG = |
100 | Logger.getLogger(ConfigurationHandler.class); | |
101 | ||
102 | /** | |
103 | * Anonymous constructor allows configuration changes. | |
104 | */ | |
105 | public ConfigurationHandler() { | |
106 | 0 | this(true); |
107 | 0 | } |
108 | ||
109 | /** | |
110 | * Constructor which optionally allows configuration changes. | |
111 | * | |
112 | * @param c indicates if the configuration can be changed | |
113 | */ | |
114 | public ConfigurationHandler(boolean c) { | |
115 | 900 | super(); |
116 | 900 | changeable = c; |
117 | 900 | } |
118 | ||
119 | /** | |
120 | * Returns a default configuration path. This could be a filename | |
121 | * or a URL. It is not guaranteed to be usable across different | |
122 | * implementations of ConfigurationHandler. | |
123 | * | |
124 | * @return the default configuration path or url. | |
125 | */ | |
126 | public abstract String getDefaultPath(); | |
127 | ||
128 | /** | |
129 | * Internal worker which is called prior to any getValue | |
130 | * or setValue to ensure that the default load is done if it was not | |
131 | * loaded previously. | |
132 | */ | |
133 | private void loadIfNecessary() { | |
134 | 454266 | if (!loaded) { |
135 | 0 | loadDefault(); |
136 | } | |
137 | 454266 | } |
138 | ||
139 | /** | |
140 | * Load the configuration from the default location. | |
141 | * | |
142 | * @return true if this call loaded the configuration, | |
143 | * otherwise false, not distinguishing between a load | |
144 | * error or a previously loaded configuration. | |
145 | * | |
146 | * @see #isLoaded | |
147 | */ | |
148 | public final boolean loadDefault() { | |
149 | // Only allow one load | |
150 | 900 | if (loaded) { |
151 | 0 | return false; |
152 | } | |
153 | ||
154 | 900 | boolean status = load(new File(getDefaultPath())); |
155 | 900 | if (!status) { |
156 | 0 | status = loadUnspecified(); |
157 | } | |
158 | 900 | loaded = true; |
159 | 900 | return status; |
160 | } | |
161 | ||
162 | /** | |
163 | * Save the configuration to the location it was loaded from. | |
164 | * Do not force it if the configuration was not loaded already. | |
165 | * | |
166 | * @return true if the save was successful, false if it was not | |
167 | * attempted or encountered an error. | |
168 | */ | |
169 | public final boolean saveDefault() { | |
170 | 0 | return saveDefault(false); |
171 | } | |
172 | ||
173 | /** | |
174 | * Save the configuration to the location it was loaded from. | |
175 | * | |
176 | * @param force the save even if it would not normally be done. | |
177 | * @return true if the save was successful, false if it was not | |
178 | * attempted or encountered an error. | |
179 | */ | |
180 | public final boolean saveDefault(boolean force) { | |
181 | 0 | if (force) { |
182 | 0 | File toFile = new File(getDefaultPath()); |
183 | 0 | boolean saved = saveFile(toFile); |
184 | 0 | if (saved) { |
185 | 0 | loadedFromFile = toFile; |
186 | } | |
187 | 0 | return saved; |
188 | } | |
189 | 0 | if (!loaded) { |
190 | 0 | return false; |
191 | } | |
192 | ||
193 | 0 | if (loadedFromFile != null) { |
194 | 0 | return saveFile(loadedFromFile); |
195 | } | |
196 | 0 | if (loadedFromURL != null) { |
197 | 0 | return saveURL(loadedFromURL); |
198 | } | |
199 | 0 | return false; |
200 | } | |
201 | ||
202 | /** | |
203 | * Indicates whether the configuration can be saved. | |
204 | * | |
205 | * @return true if the configuration can be saved. | |
206 | */ | |
207 | 0 | public final boolean isChangeable() { return changeable; } |
208 | ||
209 | /** | |
210 | * Indicates whether the configuration has been loaded. | |
211 | * | |
212 | * @return true if the configuration has been loaded. | |
213 | */ | |
214 | 0 | public final boolean isLoaded() { return loaded; } |
215 | ||
216 | /** | |
217 | * Load the configuration from a <code>File</code>. | |
218 | * | |
219 | * @param file to load from. | |
220 | * @return true if this call loaded the configuration, | |
221 | * otherwise false, not distinguishing between a load | |
222 | * error or a previously loaded configuration. | |
223 | */ | |
224 | public final boolean load(File file) { | |
225 | 900 | boolean status = loadFile(file); |
226 | 900 | if (status) { |
227 | 900 | if (pcl != null) { |
228 | 0 | pcl.firePropertyChange(Configuration.FILE_LOADED, null, file); |
229 | } | |
230 | 900 | loadedFromFile = file; |
231 | } | |
232 | 900 | return status; |
233 | } | |
234 | ||
235 | /** | |
236 | * Load the configuration from a <code>URL</code>. | |
237 | * | |
238 | * @param url to load from. | |
239 | * @return true if this call loaded the configuration, | |
240 | * otherwise false, not distinguishing between a load | |
241 | * error or a previously loaded configuration. | |
242 | */ | |
243 | public final boolean load(URL url) { | |
244 | 0 | boolean status = loadURL(url); |
245 | 0 | if (status) { |
246 | 0 | if (pcl != null) { |
247 | 0 | pcl.firePropertyChange(Configuration.URL_LOADED, null, url); |
248 | } | |
249 | 0 | loadedFromURL = url; |
250 | } | |
251 | 0 | return status; |
252 | } | |
253 | ||
254 | /** | |
255 | * Save the configuration to a <code>File</code>. | |
256 | * | |
257 | * @param file to save to. | |
258 | * @return true if this call saved the configuration, | |
259 | * otherwise false. | |
260 | */ | |
261 | public final boolean save(File file) { | |
262 | 0 | if (!loaded) { |
263 | 0 | return false; |
264 | } | |
265 | 0 | boolean status = saveFile(file); |
266 | 0 | if (status) { |
267 | 0 | if (pcl != null) { |
268 | 0 | pcl.firePropertyChange(Configuration.FILE_SAVED, null, file); |
269 | } | |
270 | } | |
271 | 0 | return status; |
272 | } | |
273 | ||
274 | /** | |
275 | * Save the configuration to a <code>URL</code>. | |
276 | * | |
277 | * @param url to save to. | |
278 | * @return true if this call saved the configuration, | |
279 | * otherwise false. | |
280 | */ | |
281 | public final boolean save(URL url) { | |
282 | 0 | if (!loaded) { |
283 | 0 | return false; |
284 | } | |
285 | 0 | boolean status = saveURL(url); |
286 | 0 | if (status) { |
287 | 0 | if (pcl != null) { |
288 | 0 | pcl.firePropertyChange(Configuration.URL_SAVED, null, url); |
289 | } | |
290 | } | |
291 | 0 | return status; |
292 | } | |
293 | ||
294 | /** | |
295 | * Returns the string value of a configuration property. | |
296 | * | |
297 | * @param key the configuration key to return. | |
298 | * @param defaultValue the default value key to return | |
299 | * if the key is not found. | |
300 | * | |
301 | * @return the value of the key or the default value | |
302 | * if the key does not exist. | |
303 | */ | |
304 | public final String getString(ConfigurationKey key, String defaultValue) { | |
305 | 92707 | loadIfNecessary(); |
306 | 92707 | return getValue(key.getKey(), defaultValue); |
307 | } | |
308 | ||
309 | /** | |
310 | * Returns the numeric value of a configuration property. | |
311 | * | |
312 | * @param key the configuration key to return. | |
313 | * @param defaultValue the default value key to return | |
314 | * if the key is not found. | |
315 | * | |
316 | * @return the value of the key or the default value | |
317 | * if the key does not exist. | |
318 | */ | |
319 | public final int getInteger(ConfigurationKey key, int defaultValue) { | |
320 | 11094 | loadIfNecessary(); |
321 | try { | |
322 | 11094 | String s = getValue(key.getKey(), Integer.toString(defaultValue)); |
323 | 11094 | return Integer.parseInt(s); |
324 | 0 | } catch (NumberFormatException nfe) { |
325 | 0 | return defaultValue; |
326 | } | |
327 | } | |
328 | ||
329 | /** | |
330 | * Returns the numeric value of a configuration property. | |
331 | * | |
332 | * @param key the configuration key to return. | |
333 | * @param defaultValue the default value key to return | |
334 | * if the key is not found. | |
335 | * | |
336 | * @return the value of the key or the default value | |
337 | * if the key does not exist. | |
338 | */ | |
339 | public final double getDouble(ConfigurationKey key, double defaultValue) { | |
340 | 0 | loadIfNecessary(); |
341 | try { | |
342 | 0 | String s = getValue(key.getKey(), Double.toString(defaultValue)); |
343 | 0 | return Double.parseDouble(s); |
344 | 0 | } catch (NumberFormatException nfe) { |
345 | 0 | return defaultValue; |
346 | } | |
347 | } | |
348 | ||
349 | /** | |
350 | * Returns the boolean value of a configuration property. | |
351 | * | |
352 | * @param key the configuration key to return. | |
353 | * @param defaultValue the default value key to return | |
354 | * if the key is not found. | |
355 | * | |
356 | * @return the value of the key or the default value | |
357 | * if the key does not exist. | |
358 | */ | |
359 | public final boolean getBoolean(ConfigurationKey key, | |
360 | boolean defaultValue) { | |
361 | 148284 | loadIfNecessary(); |
362 | 148284 | Boolean dflt = Boolean.valueOf(defaultValue); |
363 | 148284 | Boolean b = |
364 | key != null | |
365 | ? Boolean.valueOf(getValue(key.getKey(), dflt.toString())) | |
366 | : dflt; | |
367 | 148284 | return b.booleanValue(); |
368 | } | |
369 | ||
370 | /** | |
371 | * Internal routine which calls the abstract setValue and handles | |
372 | * all necessary functionality including firing property change | |
373 | * notifications and tracing. | |
374 | * | |
375 | * @param key the configuration key to modify. | |
376 | * @param newValue the new value of the key. | |
377 | */ | |
378 | private synchronized void workerSetValue(ConfigurationKey key, | |
379 | String newValue) { | |
380 | 202181 | loadIfNecessary(); |
381 | ||
382 | 202181 | String oldValue = getValue(key.getKey(), ""); |
383 | 202181 | setValue(key.getKey(), newValue); |
384 | 202181 | if (pcl != null) { |
385 | 202181 | pcl.firePropertyChange(key.getKey(), oldValue, newValue); |
386 | } | |
387 | 202181 | } |
388 | ||
389 | /** | |
390 | * Sets the string value of a configuration property. | |
391 | * | |
392 | * @param key the configuration key to modify. | |
393 | * @param newValue the value to set the key to. | |
394 | */ | |
395 | public final void setString(ConfigurationKey key, String newValue) { | |
396 | 2731 | workerSetValue(key, newValue); |
397 | 2731 | } |
398 | ||
399 | /** | |
400 | * Sets the numeric value of a configuration property. | |
401 | * | |
402 | * @param key the configuration key to modify. | |
403 | * @param value the value to set the key to. | |
404 | */ | |
405 | public final void setInteger(ConfigurationKey key, int value) { | |
406 | 1800 | workerSetValue(key, Integer.toString(value)); |
407 | 1800 | } |
408 | ||
409 | /** | |
410 | * Sets the numeric value of a configuration property. | |
411 | * | |
412 | * @param key the configuration key to modify. | |
413 | * @param value the value to set the key to. | |
414 | */ | |
415 | public final void setDouble(ConfigurationKey key, double value) { | |
416 | 0 | workerSetValue(key, Double.toString(value)); |
417 | 0 | } |
418 | ||
419 | /** | |
420 | * Sets the boolean value of a configuration property. | |
421 | * | |
422 | * @param key the configuration key to modify. | |
423 | * @param value the value to set the key to. | |
424 | */ | |
425 | public final void setBoolean(ConfigurationKey key, boolean value) { | |
426 | 197650 | Boolean bool = Boolean.valueOf(value); |
427 | 197650 | workerSetValue(key, bool.toString()); |
428 | 197650 | } |
429 | ||
430 | /** | |
431 | * Adds a property change listener. | |
432 | * | |
433 | * @param p The class which will listen for property changes. | |
434 | */ | |
435 | public final void addListener(PropertyChangeListener p) { | |
436 | 0 | if (pcl == null) { |
437 | 0 | pcl = new PropertyChangeSupport(this); |
438 | } | |
439 | 0 | LOG.debug("addPropertyChangeListener(" + p + ")"); |
440 | 0 | pcl.addPropertyChangeListener(p); |
441 | 0 | } |
442 | ||
443 | /** | |
444 | * Removes a property change listener. | |
445 | * | |
446 | * @param p The class to remove as a property change listener. | |
447 | */ | |
448 | public final void removeListener(PropertyChangeListener p) { | |
449 | 0 | if (pcl != null) { |
450 | 0 | LOG.debug("removePropertyChangeListener()"); |
451 | 0 | pcl.removePropertyChangeListener(p); |
452 | } | |
453 | 0 | } |
454 | ||
455 | /** | |
456 | * Adds a property change listener.Static for simplicity of use. | |
457 | * | |
458 | * @param key The specific key to listen for. | |
459 | * @param p The class which will listen for property changes. | |
460 | */ | |
461 | public final void addListener(ConfigurationKey key, | |
462 | PropertyChangeListener p) { | |
463 | 13500 | if (pcl == null) { |
464 | 900 | pcl = new PropertyChangeSupport(this); |
465 | } | |
466 | 13500 | LOG.debug("addPropertyChangeListener(" |
467 | + key.getKey() + ")"); | |
468 | 13500 | pcl.addPropertyChangeListener(key.getKey(), p); |
469 | 13500 | } |
470 | ||
471 | /** | |
472 | * Removes a property change listener. | |
473 | * | |
474 | * @param key The specific key being listened for. | |
475 | * @param p The class to remove as a property change listener. | |
476 | */ | |
477 | public final void removeListener(ConfigurationKey key, | |
478 | PropertyChangeListener p) { | |
479 | 0 | if (pcl != null) { |
480 | 0 | LOG.debug("removePropertyChangeListener(" |
481 | + key.getKey() + ")"); | |
482 | 0 | pcl.removePropertyChangeListener(key.getKey(), p); |
483 | } | |
484 | 0 | } |
485 | ||
486 | /** | |
487 | * Internal processing to load from an unspecified source. | |
488 | * | |
489 | * @return true if the load was successful, otherwise false. | |
490 | */ | |
491 | boolean loadUnspecified() { | |
492 | 0 | return false; |
493 | } | |
494 | ||
495 | /** | |
496 | * Internal processing to save to an unspecified source. | |
497 | * | |
498 | * @return true if the save was successful, otherwise false. | |
499 | */ | |
500 | boolean saveUnspecified() { | |
501 | 0 | return false; |
502 | } | |
503 | ||
504 | /** | |
505 | * Internal processing to load a <code>File</code>. | |
506 | * | |
507 | * @param file the file to load. | |
508 | * | |
509 | * @return true if the load was successful, otherwise false. | |
510 | */ | |
511 | public abstract boolean loadFile(File file); | |
512 | ||
513 | /** | |
514 | * Internal processing to load a <code>URL</code>. | |
515 | * | |
516 | * @param url the url to load. | |
517 | * | |
518 | * @return true if the load was successful, otherwise false. | |
519 | */ | |
520 | public abstract boolean loadURL(URL url); | |
521 | ||
522 | /** | |
523 | * Internal processing to save a <code>File</code>. | |
524 | * | |
525 | * @param file the file to save. | |
526 | * | |
527 | * @return true if the save was successful, otherwise false. | |
528 | */ | |
529 | public abstract boolean saveFile(File file); | |
530 | ||
531 | /** | |
532 | * Internal processing to save a <code>URL</code>. | |
533 | * | |
534 | * @param url the url to save. | |
535 | * | |
536 | * @return true if the save was successful, otherwise false. | |
537 | */ | |
538 | public abstract boolean saveURL(URL url); | |
539 | ||
540 | /** | |
541 | * Allows query for the existence of a configuration property. | |
542 | * This may be overridden if the implementation has a | |
543 | * more efficient method. | |
544 | * | |
545 | * @param key the property being checked. | |
546 | * | |
547 | * @return true if the key exists, otherwise false. | |
548 | */ | |
549 | public boolean hasKey(ConfigurationKey key) { | |
550 | 0 | return getValue(key.getKey(), "true").equals(getValue(key.getKey(), |
551 | "false")); | |
552 | } | |
553 | ||
554 | /** | |
555 | * Returns the string value of a configuration property. | |
556 | * | |
557 | * @param key the configuration key to return. | |
558 | * @param defaultValue the configuration key to return. | |
559 | * | |
560 | * @return the value of the key or the default value | |
561 | * if the key does not exist. | |
562 | */ | |
563 | public abstract String getValue(String key, String defaultValue); | |
564 | ||
565 | /** | |
566 | * Sets the string value of a configuration property. | |
567 | * | |
568 | * @param key the configuration key to modify. | |
569 | * @param value the value to set the key to. | |
570 | */ | |
571 | public abstract void setValue(String key, String value); | |
572 | ||
573 | /** | |
574 | * Remove the property and the assotiated value. | |
575 | * | |
576 | * @param key The key to remove. | |
577 | */ | |
578 | public abstract void remove(String key); | |
579 | } | |
580 | ||
581 |