Coverage Report - org.argouml.configuration.ConfigurationHandler
 
Classes in this File Line Coverage Branch Coverage Complexity
ConfigurationHandler
39%
43/110
18%
9/48
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