From f406bc46c653133b832ee20e7303aabb18d70426 Mon Sep 17 00:00:00 2001 From: mdb Date: Wed, 31 Jan 2007 00:41:25 +0000 Subject: [PATCH] git-svn-id: https://samskivert.googlecode.com/svn/trunk@2043 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- .../com/samskivert/swing/RuntimeAdjust.java | 58 +- .../samskivert/swing/tests/AdjustTestApp.java | 4 +- .../com/samskivert/swing/util/ButtonUtil.java | 31 +- src/java/com/samskivert/util/Config.java | 536 ++++-------------- src/java/com/samskivert/util/PrefsConfig.java | 325 +++++++++++ .../com/samskivert/util/tests/ConfigTest.java | 7 +- 6 files changed, 470 insertions(+), 491 deletions(-) create mode 100644 src/java/com/samskivert/util/PrefsConfig.java diff --git a/src/java/com/samskivert/swing/RuntimeAdjust.java b/src/java/com/samskivert/swing/RuntimeAdjust.java index 8252f060..91f0bc89 100644 --- a/src/java/com/samskivert/swing/RuntimeAdjust.java +++ b/src/java/com/samskivert/swing/RuntimeAdjust.java @@ -31,32 +31,28 @@ import javax.swing.Scrollable; import com.samskivert.Log; import com.samskivert.util.ComparableArrayList; -import com.samskivert.util.Config; +import com.samskivert.util.PrefsConfig; import com.samskivert.util.DebugChords; import com.samskivert.util.ListUtil; import com.samskivert.util.StringUtil; /** - * Provides a service where named variables can be registered as - * adjustable by the developer at runtime. Generally a special key is - * configured (via {@link DebugChords}) to pop up the adjustable variables - * interface which can then be used to toggle booleans, change integer - * values and generally adjust debugging and tuning parameters. This is - * not meant to be an interface for end-user configurable parameters, but - * to allow the developer to tweak runtime parameters more easily. + * Provides a service where named variables can be registered as adjustable by the developer at + * runtime. Generally a special key is configured (via {@link DebugChords}) to pop up the + * adjustable variables interface which can then be used to toggle booleans, change integer values + * and generally adjust debugging and tuning parameters. This is not meant to be an interface for + * end-user configurable parameters, but to allow the developer to tweak runtime parameters more + * easily. * - *

Adjustments are bound to a {@link Config} property which can be - * changed through the config interface or through the bound runtime - * adjust. + *

Adjustments are bound to a {@link PrefsConfig} property which can be changed through the + * config interface or through the bound runtime adjust. * - *

Note: adjusts are meant to be arranged in a two level - * hierarchy. An adjust's name, therefore, should be of the form: - * library.package.adjustment. The package - * component can consist of multiple words joined with a period, but the - * library will always be the first word before the first - * period and the adjustment always the last word after the - * final period. This is mainly only important for organizing the runtime - * adjustment editing interface. + *

Note: adjusts are meant to be arranged in a two level hierarchy. An adjust's name, + * therefore, should be of the form: library.package.adjustment. The + * package component can consist of multiple words joined with a period, but the + * library will always be the first word before the first period and the + * adjustment always the last word after the final period. This is mainly only + * important for organizing the runtime adjustment editing interface. */ public class RuntimeAdjust { @@ -147,8 +143,7 @@ public class RuntimeAdjust public static class BooleanAdjust extends Adjust implements ActionListener { - public BooleanAdjust (String descrip, String name, - Config config, boolean defval) + public BooleanAdjust (String descrip, String name, PrefsConfig config, boolean defval) { super(descrip, name, config); _value = _config.getValue(_name, defval); @@ -197,8 +192,7 @@ public class RuntimeAdjust /** Provides runtime adjustable integer variables. */ public static class IntAdjust extends TextFieldAdjust { - public IntAdjust (String descrip, String name, - Config config, int defval) + public IntAdjust (String descrip, String name, PrefsConfig config, int defval) { super(descrip, name, config); _value = _config.getValue(_name, defval); @@ -251,8 +245,8 @@ public class RuntimeAdjust public static class EnumAdjust extends Adjust implements ActionListener { - public EnumAdjust (String descrip, String name, - Config config, String[] values, String defval) + public EnumAdjust (String descrip, String name, PrefsConfig config, + String[] values, String defval) { super(descrip, name, config); _values = values; @@ -310,9 +304,8 @@ public class RuntimeAdjust public static class FileAdjust extends Adjust implements ActionListener { - public FileAdjust (String descrip, String name, - Config config, boolean directoriesOnly, - String defval) + public FileAdjust (String descrip, String name, PrefsConfig config, + boolean directoriesOnly, String defval) { super(descrip, name, config); _value = _config.getValue(_name, defval); @@ -431,7 +424,7 @@ public class RuntimeAdjust protected abstract static class TextFieldAdjust extends Adjust implements ActionListener, FocusListener { - public TextFieldAdjust (String descrip, String name, Config config) + public TextFieldAdjust (String descrip, String name, PrefsConfig config) { super(descrip, name, config); } @@ -464,7 +457,7 @@ public class RuntimeAdjust protected abstract static class Adjust implements PropertyChangeListener, Comparable { - public Adjust (String descrip, String name, Config config) + public Adjust (String descrip, String name, PrefsConfig config) { _name = name; _descrip = descrip; @@ -550,10 +543,9 @@ public class RuntimeAdjust } protected String _name, _descrip; - protected Config _config; + protected PrefsConfig _config; protected JPanel _editor; } - protected static ComparableArrayList _adjusts = - new ComparableArrayList(); + protected static ComparableArrayList _adjusts = new ComparableArrayList(); } diff --git a/src/java/com/samskivert/swing/tests/AdjustTestApp.java b/src/java/com/samskivert/swing/tests/AdjustTestApp.java index 07859b23..ae27fe78 100644 --- a/src/java/com/samskivert/swing/tests/AdjustTestApp.java +++ b/src/java/com/samskivert/swing/tests/AdjustTestApp.java @@ -9,7 +9,7 @@ import javax.swing.JComponent; import javax.swing.JFrame; import com.samskivert.swing.RuntimeAdjust; -import com.samskivert.util.Config; +import com.samskivert.util.PrefsConfig; /** * Does something extraordinary. @@ -18,7 +18,7 @@ public class AdjustTestApp { public static void main (String[] args) { - Config config = new Config("test"); + PrefsConfig config = new PrefsConfig("test"); new RuntimeAdjust.IntAdjust( "This is a test adjustment. It is nice.", "samskivert.test.int_adjust1", config, 5); diff --git a/src/java/com/samskivert/swing/util/ButtonUtil.java b/src/java/com/samskivert/swing/util/ButtonUtil.java index 4b3f791e..6ce18f4c 100644 --- a/src/java/com/samskivert/swing/util/ButtonUtil.java +++ b/src/java/com/samskivert/swing/util/ButtonUtil.java @@ -16,7 +16,7 @@ import javax.swing.JToggleButton; import javax.swing.event.AncestorEvent; import javax.swing.event.AncestorListener; -import com.samskivert.util.Config; +import com.samskivert.util.PrefsConfig; import com.samskivert.util.IntListUtil; /** @@ -25,8 +25,8 @@ import com.samskivert.util.IntListUtil; public class ButtonUtil { /** - * Set the specified button such that it alternates between being - * selected and not whenever it is pushed. + * Set the specified button such that it alternates between being selected and not whenever it + * is pushed. */ public static synchronized void setToggling (AbstractButton b) { @@ -44,28 +44,25 @@ public class ButtonUtil } /** - * Binds the supplied button to the named boolean property in the - * supplied config repository. When the button is pressed, it will - * update the config property and when the config property is changed - * (by the button or by other means) it will update the selected state - * of the button. When the button is made non-visible, it will be - * unbound to the config's property and rebound again if it is once - * again visible. + * Binds the supplied button to the named boolean property in the supplied config repository. + * When the button is pressed, it will update the config property and when the config property + * is changed (by the button or by other means) it will update the selected state of the + * button. When the button is made non-visible, it will be unbound to the config's property and + * rebound again if it is once again visible. */ public static void bindToProperty ( - String property, Config config, AbstractButton button, boolean defval) + String property, PrefsConfig config, AbstractButton button, boolean defval) { // create a config binding which will take care of everything new ButtonConfigBinding(property, config, button, defval); } /** - * Configure the specified button to cause the specified - * property to cycle through the specified values whenever the button is - * pressed. + * Configure the specified button to cause the specified property to cycle through the + * specified values whenever the button is pressed. */ public static ActionListener cycleToProperty ( - final String property, final Config config, AbstractButton button, + final String property, final PrefsConfig config, AbstractButton button, final int[] values) { ActionListener al = new ActionListener() { @@ -87,7 +84,7 @@ public class ButtonUtil protected static class ButtonConfigBinding implements AncestorListener, PropertyChangeListener, ItemListener { - public ButtonConfigBinding (String property, Config config, + public ButtonConfigBinding (String property, PrefsConfig config, AbstractButton button, boolean defval) { _property = property; @@ -136,7 +133,7 @@ public class ButtonUtil } protected String _property; - protected Config _config; + protected PrefsConfig _config; protected AbstractButton _button; protected boolean _defval; } diff --git a/src/java/com/samskivert/util/Config.java b/src/java/com/samskivert/util/Config.java index b97d1ad1..08c9e505 100644 --- a/src/java/com/samskivert/util/Config.java +++ b/src/java/com/samskivert/util/Config.java @@ -3,7 +3,7 @@ // // samskivert library - useful routines for java programs // Copyright (C) 2001 Michael Bayne -// +// // This library is free software; you can redistribute it and/or modify it // under the terms of the GNU Lesser General Public License as published // by the Free Software Foundation; either version 2.1 of the License, or @@ -20,12 +20,6 @@ package com.samskivert.util; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.security.AccessControlException; -import java.security.AccessController; -import java.security.PrivilegedAction; - import java.io.FileNotFoundException; import java.io.IOException; @@ -34,22 +28,16 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Properties; -import java.util.prefs.AbstractPreferences; -import java.util.prefs.BackingStoreException; -import java.util.prefs.Preferences; - import com.samskivert.Log; /** - * The config class provides a unified interaface to application - * configuration information. It takes care of loading properties files - * (done via the classpath) and allows for overriding and inheriting of - * properties values (see {@link ConfigUtil#loadInheritedProperties}). + * The config class provides a unified interaface to application configuration information. It + * takes care of loading properties files (done via the classpath) and allows for overriding and + * inheriting of properties values (see {@link ConfigUtil#loadInheritedProperties}). * - *

A common pattern is to create, for each package that shares - * configuration information, a singleton class containing a config object - * that is configured to load its data from a single configuration - * file. For example: + *

A common pattern is to create, for each package that shares configuration information, a + * singleton class containing a config object that is configured to load its data from a single + * configuration file. For example: * *

  * public class FooConfig
@@ -60,9 +48,8 @@ import com.samskivert.Log;
  * }
  * 
* - * which would look for com/fribitz/foo.properties in the - * classpath and serve up those configuration values when requests were - * made from FooConfig.config. For example: + * which would look for com/fribitz/foo.properties in the classpath and serve up those + * configuration values when requests were made from FooConfig.config. For example: * *
  *     int fiddles = FooConfig.config.getValue(FooConfig.FIDDLES, 0);
@@ -71,8 +58,7 @@ import com.samskivert.Log;
  *     }
  * 
* - * An even better approach involves creating accessors for all defined - * configuration properties: + * An even better approach involves creating accessors for all defined configuration properties: * *
  * public class FooConfig
@@ -90,23 +76,16 @@ import com.samskivert.Log;
  * }
  * 
* - * This allows the default value for fiddles to be specified - * in one place and simplifies life for the caller who can now simply - * request FooConfig.getFiddles(). + * This allows the default value for fiddles to be specified in one place and + * simplifies life for the caller who can now simply request FooConfig.getFiddles(). * - *

The config class allows one to override configuration values - * persistently, using the standard Java {@link Preferences} facilities to - * maintain the overridden values. If a property is {@link #setValue}d in - * a configuration object, it will remain overridden in between - * invocations of the application (leveraging the benefits of the - * pluggable preferences backends provided by the standard Java - * preferences facilities). + * @see PrefsConfig */ public class Config { /** - * Constructs a new config object which will obtain configuration - * information from the specified properties bundle. + * Constructs a new config object which will obtain configuration information from the + * specified properties bundle. */ public Config (String path) { @@ -121,119 +100,59 @@ public class Config ConfigUtil.loadInheritedProperties(ppath, _props); } catch (FileNotFoundException fnfe) { - Log.debug("No properties file found to back config " + - "[path=" + path + "]."); + Log.debug("No properties file found to back config [path=" + path + "]."); } catch (IOException ioe) { - Log.warning("Unable to load configuration [path=" + path + - ", ioe=" + ioe + "]."); - } - - // get a handle on the preferences instance that we'll use to - // override values in the properties file - try { - _prefs = Preferences.userRoot().node(path); - } catch (AccessControlException ace) { - // security manager won't let us access prefs, no problem! - Log.info("Can't access preferences [path=" + path + "]."); - _prefs = new NullPreferences(); + Log.warning("Unable to load configuration [path=" + path + ", ioe=" + ioe + "]."); } } /** - * Constructs a config object which will obtain information from the - * supplied properties, rooted at the specified path in the - * preferences hieriarchy. + * Constructs a config object which will obtain information from the supplied properties. */ - public Config (final String path, Properties props) + public Config (String path, Properties props) { _props = props; - try { - _prefs = Preferences.userRoot().node(path); - } catch (AccessControlException ace) { - // security manager won't let us access prefs, no problem! - Log.info("Can't access preferences [path=" + path + "]."); - _prefs = new NullPreferences(); - } } /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. If - * the property specified in the file is poorly formatted (not and - * integer, not in proper array specification), a warning message will - * be logged and the default value will be returned. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * If the property specified in the file is poorly formatted (not and integer, not in proper + * array specification), a warning message will be logged and the default value will be + * returned. * * @param name name of the property. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public int getValue (String name, int defval) - { - return _prefs.getInt(name, getDefValue(name, defval)); - } - - /** - * Returns the value specified in the properties override file. - */ - protected int getDefValue (String name, int defval) { String val = _props.getProperty(name); if (val != null) { try { - // handles base 10, hex values, etc. - return Integer.decode(val).intValue(); + return Integer.decode(val).intValue(); // handles base 10, hex values, etc. } catch (NumberFormatException nfe) { - Log.warning("Malformed integer property [name=" + name + - ", value=" + val + "]."); + Log.warning("Malformed integer property [name=" + name + ", value=" + val + "]."); } } return defval; } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, int value) - { - Integer oldValue = null; - if (_prefs.get(name, null) != null || - _props.getProperty(name) != null) { - oldValue = Integer.valueOf( - _prefs.getInt(name, getDefValue(name, 0))); - } - - _prefs.putInt(name, value); - _propsup.firePropertyChange(name, oldValue, Integer.valueOf(value)); - } - - /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. If - * the property specified in the file is poorly formatted (not and - * integer, not in proper array specification), a warning message will - * be logged and the default value will be returned. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * If the property specified in the file is poorly formatted (not and integer, not in proper + * array specification), a warning message will be logged and the default value will be + * returned. * * @param name name of the property. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public long getValue (String name, long defval) - { - return _prefs.getLong(name, getDefValue(name, defval)); - } - - /** - * Returns the value specified in the properties override file. - */ - protected long getDefValue (String name, long defval) { String val = _props.getProperty(name); if (val != null) { @@ -248,45 +167,18 @@ public class Config } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, long value) - { - Long oldValue = null; - if (_prefs.get(name, null) != null || - _props.getProperty(name) != null) { - oldValue = Long.valueOf( - _prefs.getLong(name, getDefValue(name, 0L))); - } - - _prefs.putLong(name, value); - _propsup.firePropertyChange(name, oldValue, Long.valueOf(value)); - } - - /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. If - * the property specified in the file is poorly formatted (not and - * integer, not in proper array specification), a warning message will - * be logged and the default value will be returned. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * If the property specified in the file is poorly formatted (not and integer, not in proper + * array specification), a warning message will be logged and the default value will be + * returned. * * @param name name of the property. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public float getValue (String name, float defval) - { - return _prefs.getFloat(name, getDefValue(name, defval)); - } - - /** - * Returns the value specified in the properties override file. - */ - protected float getDefValue (String name, float defval) { String val = _props.getProperty(name); if (val != null) { @@ -301,79 +193,17 @@ public class Config } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, float value) - { - Float oldValue = null; - if (_prefs.get(name, null) != null || - _props.getProperty(name) != null) { - oldValue = Float.valueOf( - _prefs.getFloat(name, getDefValue(name, 0f))); - } - - _prefs.putFloat(name, value); - _propsup.firePropertyChange(name, oldValue, Float.valueOf(value)); - } - - /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * The returned value will be false if the config value is "false" + * (case-insensitive), else the return value will be true. * * @param name the name of the property to be fetched. - * @param defval the value to return if the property is not specified - * in the config file. - * - * @return the value of the requested property. - */ - public String getValue (String name, String defval) - { - // if there is a value, parse it into an integer - String val = _props.getProperty(name); - if (val != null) { - defval = val; - } - - // finally look for an overridden value - return _prefs.get(name, defval); - } - - /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, String value) - { - String oldValue = getValue(name, (String)null); - _prefs.put(name, value); - _propsup.firePropertyChange(name, oldValue, value); - } - - /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned - * instead. The returned value will be false if the - * config value is "false" (case-insensitive), else - * the return value will be true. - * - * @param name the name of the property to be fetched. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public boolean getValue (String name, boolean defval) - { - return _prefs.getBoolean(name, getDefValue(name, defval)); - } - - /** - * Returns the value specified in the properties override file. - */ - protected boolean getDefValue (String name, boolean defval) { String val = _props.getProperty(name); if (val != null) { @@ -383,41 +213,35 @@ public class Config } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * + * @param name the name of the property to be fetched. + * @param defval the value to return if the property is not specified in the config file. + * + * @return the value of the requested property. */ - public void setValue (String name, boolean value) + public String getValue (String name, String defval) { - Boolean oldValue = null; - if (_prefs.get(name, null) != null || - _props.getProperty(name) != null) { - oldValue = Boolean.valueOf( - _prefs.getBoolean(name, getDefValue(name, false))); - } - - _prefs.putBoolean(name, value); - _propsup.firePropertyChange(name, oldValue, Boolean.valueOf(value)); + return _props.getProperty(name, defval); } /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. If - * the property specified in the file is poorly formatted (not and - * integer, not in proper array specification), a warning message will - * be logged and the default value will be returned. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * If the property specified in the file is poorly formatted (not and integer, not in proper + * array specification), a warning message will be logged and the default value will be + * returned. * * @param name the name of the property to be fetched. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public int[] getValue (String name, int[] defval) { - // look up the value in the configuration file and use that to - // look up any overridden value - String val = _prefs.get(name, _props.getProperty(name)); + // look up the value in the configuration file and use that to look up any overridden value + String val = getValue(name, (String)null); int[] result = defval; // parse it into an array of ints @@ -434,35 +258,21 @@ public class Config } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, int[] value) - { - int[] oldValue = getValue(name, (int[])null); - _prefs.put(name, StringUtil.toString(value, "", "")); - _propsup.firePropertyChange(name, oldValue, value); - } - - /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. If - * the property specified in the file is poorly formatted (not and - * integer, not in proper array specification), a warning message will - * be logged and the default value will be returned. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * If the property specified in the file is poorly formatted (not and integer, not in proper + * array specification), a warning message will be logged and the default value will be + * returned. * * @param name the name of the property to be fetched. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public long[] getValue (String name, long[] defval) { - // look up the value in the configuration file and use that to - // look up any overridden value - String val = _prefs.get(name, _props.getProperty(name)); + // look up the value in the configuration file and use that to look up any overridden value + String val = getValue(name, (String)null); long[] result = defval; // parse it into an array of longs @@ -479,35 +289,21 @@ public class Config } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, long[] value) - { - long[] oldValue = getValue(name, (long[])null); - _prefs.put(name, StringUtil.toString(value, "", "")); - _propsup.firePropertyChange(name, oldValue, value); - } - - /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. If - * the property specified in the file is poorly formatted (not a - * floating point value, not in proper array specification), a warning - * message will be logged and the default value will be returned. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * If the property specified in the file is poorly formatted (not a floating point value, not + * in proper array specification), a warning message will be logged and the default value will + * be returned. * * @param name the name of the property to be fetched. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public float[] getValue (String name, float[] defval) { - // look up the value in the configuration file and use that to - // look up any overridden value - String val = _prefs.get(name, _props.getProperty(name)); + // look up the value in the configuration file and use that to look up any overridden value + String val = getValue(name, (String)null); float[] result = defval; // parse it into an array of ints @@ -524,35 +320,21 @@ public class Config } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, float[] value) - { - float[] oldValue = getValue(name, (float[])null); - _prefs.put(name, StringUtil.toString(value, "", "")); - _propsup.firePropertyChange(name, oldValue, value); - } - - /** - * Fetches and returns the value for the specified configuration - * property. If the value is not specified in the associated - * properties file, the supplied default value is returned instead. If - * the property specified in the file is poorly formatted (not and - * integer, not in proper array specification), a warning message will - * be logged and the default value will be returned. + * Fetches and returns the value for the specified configuration property. If the value is not + * specified in the associated properties file, the supplied default value is returned instead. + * If the property specified in the file is poorly formatted (not and integer, not in proper + * array specification), a warning message will be logged and the default value will be + * returned. * * @param name the name of the property to be fetched. - * @param defval the value to return if the property is not specified - * in the config file. + * @param defval the value to return if the property is not specified in the config file. * * @return the value of the requested property. */ public String[] getValue (String name, String[] defval) { - // look up the value in the configuration file and use that to - // look up any overridden value - String val = _prefs.get(name, _props.getProperty(name)); + // look up the value in the configuration file and use that to look up any overridden value + String val = getValue(name, (String)null); String[] result = defval; // parse it into an array of ints @@ -569,78 +351,13 @@ public class Config } /** - * Sets the value of the specified preference, overriding the value - * defined in the configuration files shipped with the application. - */ - public void setValue (String name, String[] value) - { - String[] oldValue = getValue(name, (String[])null); - _prefs.put(name, StringUtil.joinEscaped(value)); - _propsup.firePropertyChange(name, oldValue, value); - } - - /** - * Remove any set value for the specified preference. - */ - public void remove (String name) - { - // we treat the old value as a String, I hope that's ok! - String oldValue = getValue(name, (String) null); - _prefs.remove(name); - _propsup.firePropertyChange(name, oldValue, null); - } - - /** - * Adds a listener that will be notified whenever any configuration - * properties are changed by a call to one of the set - * methods. - */ - public void addPropertyChangeListener (PropertyChangeListener listener) - { - _propsup.addPropertyChangeListener(listener); - } - - /** - * Removes a property change listener previously added via a call to - * {@link #addPropertyChangeListener}. - */ - public void removePropertyChangeListener (PropertyChangeListener listener) - { - _propsup.removePropertyChangeListener(listener); - } - - /** - * Adds a listener that will be notified whenever the specified - * configuration property is changed by a call to the appropriate - * set method. - */ - public void addPropertyChangeListener ( - String name, PropertyChangeListener listener) - { - _propsup.addPropertyChangeListener(name, listener); - } - - /** - * Removes a property change listener previously added via a call to - * {@link #addPropertyChangeListener(String,PropertyChangeListener)}. - */ - public void removePropertyChangeListener ( - String name, PropertyChangeListener listener) - { - _propsup.removePropertyChangeListener(name, listener); - } - - /** - * Looks up the specified string-valued configuration entry, loads the - * class with that name and instantiates a new instance of that class, - * which is returned. + * Looks up the specified string-valued configuration entry, loads the class with that name and + * instantiates a new instance of that class, which is returned. * * @param name the name of the property to be fetched. - * @param defcname the class name to use if the property is not - * specified in the config file. + * @param defcname the class name to use if the property is not specified in the config file. * - * @exception Exception thrown if any error occurs while loading or - * instantiating the class. + * @exception Exception thrown if any error occurs while loading or instantiating the class. */ public Object instantiateValue (String name, String defcname) throws Exception @@ -649,10 +366,9 @@ public class Config } /** - * Returns a properties object containing all configuration values - * that start with the supplied prefix (plus a trailing "." which will - * be added if it doesn't already exist). The keys in the - * sub-properties will have had the prefix stripped off. + * Returns a properties object containing all configuration values that start with the supplied + * prefix (plus a trailing "." which will be added if it doesn't already exist). The keys in + * the sub-properties will have had the prefix stripped off. */ public Properties getSubProperties (String prefix) { @@ -662,10 +378,9 @@ public class Config } /** - * Fills into the supplied properties object all configuration values - * that start with the supplied prefix (plus a trailing "." which will - * be added if it doesn't already exist). The keys in the - * sub-properties will have had the prefix stripped off. + * Fills into the supplied properties object all configuration values that start with the + * supplied prefix (plus a trailing "." which will be added if it doesn't already exist). The + * keys in the sub-properties will have had the prefix stripped off. */ public void getSubProperties (String prefix, Properties target) { @@ -690,75 +405,26 @@ public class Config } /** - * Returns an iterator that returns all of the configuration keys in - * this config object. + * Returns an iterator that returns all of the configuration keys in this config object. */ public Iterator keys () { - // what with all the complicated business, we just need to take - // the brute force approach and enumerate everything up front HashSet matches = new HashSet(); - - // add the keys provided in the config files - Enumeration defkeys = _props.propertyNames(); - while (defkeys.hasMoreElements()) { - matches.add((String)defkeys.nextElement()); - } - - // then add the overridden keys - try { - String[] keys = _prefs.keys(); - for (int i = 0; i < keys.length; i++) { - matches.add(keys[i]); - } - } catch (BackingStoreException bse) { - Log.warning("Unable to enumerate preferences keys " + - "[error=" + bse + "]."); - } - + enumerateKeys(matches); return matches.iterator(); } - /** This is used if we don't have security access to the preferences - * implementation that we'd like. */ - protected static class NullPreferences extends AbstractPreferences + protected void enumerateKeys (HashSet keys) { - public NullPreferences () { - super(null, ""); - } - protected void putSpi (String key, String value) { - } - protected String getSpi (String key) { - return null; - } - protected void removeSpi (String key) { - } - protected void removeNodeSpi () throws BackingStoreException { - } - protected String[] keysSpi () throws BackingStoreException { - return new String[0]; - } - protected String[] childrenNamesSpi () throws BackingStoreException { - return new String[0]; - } - protected AbstractPreferences childSpi (String name) { - return null; - } - protected void syncSpi () throws BackingStoreException { - } - protected void flushSpi () throws BackingStoreException { + Enumeration defkeys = _props.propertyNames(); + while (defkeys.hasMoreElements()) { + keys.add((String)defkeys.nextElement()); } } /** Contains the default configuration information. */ protected Properties _props; - /** Used to maintain configuration overrides. */ - protected Preferences _prefs; - - /** Used to support our property change mechanism. */ - protected PropertyChangeSupport _propsup = new PropertyChangeSupport(this); - /** The file extension used for configuration files. */ protected static final String PROPS_SUFFIX = ".properties"; } diff --git a/src/java/com/samskivert/util/PrefsConfig.java b/src/java/com/samskivert/util/PrefsConfig.java new file mode 100644 index 00000000..58342fbc --- /dev/null +++ b/src/java/com/samskivert/util/PrefsConfig.java @@ -0,0 +1,325 @@ +// +// $Id$ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2007 Michael Bayne +// +// This library is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License as published +// by the Free Software Foundation; either version 2.1 of the License, or +// (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.util; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.PrivilegedAction; + +import java.util.HashSet; +import java.util.Iterator; +import java.util.Properties; + +import java.util.prefs.AbstractPreferences; +import java.util.prefs.BackingStoreException; +import java.util.prefs.Preferences; + +import com.samskivert.Log; + +/** + * Extends the {@link Config} mechanism to allow the modification of configuration values, which + * are persisted using the Java preferences system. If a property is {@link #setValue}d, it will + * remain overridden in between invocations of the application (leveraging the benefits of the + * pluggable preferences backends provided by the standard Java preferences facilities). + */ +public class PrefsConfig extends Config +{ + /** + * Constructs a new config object which will obtain configuration information from the + * specified properties bundle. + */ + public PrefsConfig (String path) + { + super(path); + + // get a handle on the preferences instance that we'll use to override values in the + // properties file + try { + _prefs = Preferences.userRoot().node(path); + } catch (AccessControlException ace) { + // security manager won't let us access prefs, no problem! + Log.info("Can't access preferences [path=" + path + "]."); + _prefs = new NullPreferences(); + } + } + + /** + * Constructs a config object which will obtain information from the supplied properties, + * rooted at the specified path in the preferences hieriarchy. + */ + public PrefsConfig (String path, Properties props) + { + super(path, props); + + try { + _prefs = Preferences.userRoot().node(path); + } catch (AccessControlException ace) { + // security manager won't let us access prefs, no problem! + Log.info("Can't access preferences [path=" + path + "]."); + _prefs = new NullPreferences(); + } + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, int value) + { + Integer oldValue = null; + if (_prefs.get(name, null) != null || _props.getProperty(name) != null) { + oldValue = Integer.valueOf(_prefs.getInt(name, super.getValue(name, 0))); + } + + _prefs.putInt(name, value); + _propsup.firePropertyChange(name, oldValue, Integer.valueOf(value)); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, long value) + { + Long oldValue = null; + if (_prefs.get(name, null) != null || _props.getProperty(name) != null) { + oldValue = Long.valueOf(_prefs.getLong(name, super.getValue(name, 0L))); + } + + _prefs.putLong(name, value); + _propsup.firePropertyChange(name, oldValue, Long.valueOf(value)); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, float value) + { + Float oldValue = null; + if (_prefs.get(name, null) != null || _props.getProperty(name) != null) { + oldValue = Float.valueOf(_prefs.getFloat(name, super.getValue(name, 0f))); + } + + _prefs.putFloat(name, value); + _propsup.firePropertyChange(name, oldValue, Float.valueOf(value)); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, boolean value) + { + Boolean oldValue = null; + if (_prefs.get(name, null) != null || _props.getProperty(name) != null) { + oldValue = Boolean.valueOf(_prefs.getBoolean(name, super.getValue(name, false))); + } + + _prefs.putBoolean(name, value); + _propsup.firePropertyChange(name, oldValue, Boolean.valueOf(value)); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, String value) + { + String oldValue = getValue(name, (String)null); + _prefs.put(name, value); + _propsup.firePropertyChange(name, oldValue, value); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, int[] value) + { + int[] oldValue = getValue(name, (int[])null); + _prefs.put(name, StringUtil.toString(value, "", "")); + _propsup.firePropertyChange(name, oldValue, value); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, long[] value) + { + long[] oldValue = getValue(name, (long[])null); + _prefs.put(name, StringUtil.toString(value, "", "")); + _propsup.firePropertyChange(name, oldValue, value); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, float[] value) + { + float[] oldValue = getValue(name, (float[])null); + _prefs.put(name, StringUtil.toString(value, "", "")); + _propsup.firePropertyChange(name, oldValue, value); + } + + /** + * Sets the value of the specified preference, overriding the value defined in the + * configuration files shipped with the application. + */ + public void setValue (String name, String[] value) + { + String[] oldValue = getValue(name, (String[])null); + _prefs.put(name, StringUtil.joinEscaped(value)); + _propsup.firePropertyChange(name, oldValue, value); + } + + /** + * Remove any set value for the specified preference. + */ + public void remove (String name) + { + // we treat the old value as a String, I hope that's ok! + String oldValue = getValue(name, (String) null); + _prefs.remove(name); + _propsup.firePropertyChange(name, oldValue, null); + } + + /** + * Adds a listener that will be notified whenever any configuration properties are changed by a + * call to one of the set methods. + */ + public void addPropertyChangeListener (PropertyChangeListener listener) + { + _propsup.addPropertyChangeListener(listener); + } + + /** + * Removes a property change listener previously added via a call to {@link + * #addPropertyChangeListener}. + */ + public void removePropertyChangeListener (PropertyChangeListener listener) + { + _propsup.removePropertyChangeListener(listener); + } + + /** + * Adds a listener that will be notified whenever the specified configuration property is + * changed by a call to the appropriate set method. + */ + public void addPropertyChangeListener (String name, PropertyChangeListener listener) + { + _propsup.addPropertyChangeListener(name, listener); + } + + /** + * Removes a property change listener previously added via a call to {@link + * #addPropertyChangeListener(String,PropertyChangeListener)}. + */ + public void removePropertyChangeListener (String name, PropertyChangeListener listener) + { + _propsup.removePropertyChangeListener(name, listener); + } + + @Override // from Config + public int getValue (String name, int defval) + { + return _prefs.getInt(name, super.getValue(name, defval)); + } + + @Override // from Config + public long getValue (String name, long defval) + { + return _prefs.getLong(name, super.getValue(name, defval)); + } + + @Override // from Config + public float getValue (String name, float defval) + { + return _prefs.getFloat(name, super.getValue(name, defval)); + } + + @Override // from Config + public boolean getValue (String name, boolean defval) + { + return _prefs.getBoolean(name, super.getValue(name, defval)); + } + + @Override // from Config + public String getValue (String name, String defval) + { + return _prefs.get(name, super.getValue(name, defval)); + } + + @Override // from Config + protected void enumerateKeys (HashSet keys) + { + super.enumerateKeys(keys); + + try { + for (String key : _prefs.keys()) { + keys.add(key); + } + } catch (BackingStoreException bse) { + Log.warning("Unable to enumerate preferences keys [error=" + bse + "]."); + } + } + + /** This is used if we don't have security access to the preferences + * implementation that we'd like. */ + protected static class NullPreferences extends AbstractPreferences + { + public NullPreferences () { + super(null, ""); + } + protected void putSpi (String key, String value) { + } + protected String getSpi (String key) { + return null; + } + protected void removeSpi (String key) { + } + protected void removeNodeSpi () throws BackingStoreException { + } + protected String[] keysSpi () throws BackingStoreException { + return new String[0]; + } + protected String[] childrenNamesSpi () throws BackingStoreException { + return new String[0]; + } + protected AbstractPreferences childSpi (String name) { + return null; + } + protected void syncSpi () throws BackingStoreException { + } + protected void flushSpi () throws BackingStoreException { + } + } + + /** Used to maintain configuration overrides. */ + protected Preferences _prefs; + + /** Used to support our property change mechanism. */ + protected PropertyChangeSupport _propsup = new PropertyChangeSupport(this); +} diff --git a/src/java/com/samskivert/util/tests/ConfigTest.java b/src/java/com/samskivert/util/tests/ConfigTest.java index 14753031..00bdc293 100644 --- a/src/java/com/samskivert/util/tests/ConfigTest.java +++ b/src/java/com/samskivert/util/tests/ConfigTest.java @@ -9,7 +9,7 @@ import java.util.Properties; import junit.framework.Test; import junit.framework.TestCase; -import com.samskivert.util.Config; +import com.samskivert.util.PrefsConfig; import com.samskivert.util.StringUtil; /** @@ -24,7 +24,7 @@ public class ConfigTest extends TestCase public void runTest () { - Config config = new Config("rsrc/util/test"); + PrefsConfig config = new PrefsConfig("rsrc/util/test"); System.out.println("prop1: " + config.getValue("prop1", 1)); System.out.println("prop2: " + config.getValue("prop2", "two")); @@ -51,8 +51,7 @@ public class ConfigTest extends TestCase config.setValue("sub.sub3", "three"); Properties subprops = config.getSubProperties("sub"); - System.out.println("Sub: " + - StringUtil.toString(subprops.propertyNames())); + System.out.println("Sub: " + StringUtil.toString(subprops.propertyNames())); } public static Test suite ()