| /******************************************************************************* |
| * Copyright (c) 2000, 2014 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.core.runtime; |
| |
| import java.io.*; |
| import java.util.*; |
| import org.eclipse.core.internal.preferences.PreferencesService; |
| import org.eclipse.core.internal.preferences.PrefsMessages; |
| import org.eclipse.core.runtime.preferences.*; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * A table of preference settings, mapping named properties to values. Property |
| * names are non-empty strings; property values can be either booleans, |
| * non-null strings, or values of one of the primitive number types. |
| * The table consists of two, sparse, layers: the lower layer holds default values |
| * for properties, and the upper layer holds explicitly set values for properties. |
| * Normal retrieval looks for an explicitly set value for the given property in |
| * the upper layer; if there is nothing for that property in the upper layer, it |
| * next looks for a default value for the given property in the lower layer; if |
| * there is nothing for that property in the lower layer, it returns a standard |
| * default-default value. The default-default values for the primitive types are |
| * as follows: |
| * <ul> |
| * <li><code>boolean</code> = <code>false</code></li> |
| * <li><code>double</code> = <code>0.0</code></li> |
| * <li><code>float</code> = <code>0.0f</code></li> |
| * <li><code>int</code> = <code>0</code></li> |
| * <li><code>long</code> = <code>0L</code></li> |
| * <li><code>String</code> = <code>""</code> (the empty string)</li> |
| * </ul> |
| * <p> |
| * Internally, all properties values (in both layers) are stored as strings. |
| * Standard conversions to and from numeric and boolean types are performed on |
| * demand. |
| * </p> |
| * <p> |
| * The typical usage is to establish the defaults for all known properties |
| * and then restore previously stored values for properties whose values |
| * were explicitly set. The existing settings can be changed and new properties |
| * can be set (<code>setValue</code>). If the values specified is the same as |
| * the default value, the explicit setting is deleted from the top layer. |
| * It is also possible to reset a property value back to the default value |
| * using <code>setToDefault</code>. After the properties have been modified, |
| * the properties with explicit settings are written to disk. The default values |
| * are never saved. This two-tiered approach |
| * to saving and restoring property setting minimizes the number of properties |
| * that need to be persisted; indeed, the normal starting state does not require |
| * storing any properties at all. It also makes it easy to use different |
| * default settings in different environments while maintaining just those |
| * property settings the user has adjusted. |
| * </p> |
| * <p> |
| * A property change event is reported whenever a property's value actually |
| * changes (either through <code>setValue</code>, <code>setToDefault</code>). |
| * Note, however, that manipulating default values (with <code>setDefault</code>) |
| * does not cause any events to be reported. |
| * </p> |
| * <p> |
| * Clients may instantiate this class. |
| * </p> |
| * <p> |
| * The implementation is based on a pair of internal |
| * <code>java.util.Properties</code> objects, one holding explicitly set values |
| * (set using <code>setValue</code>), the other holding the default values |
| * (set using <code>setDefaultValue</code>). The <code>load</code> and |
| * <code>store</code> methods persist the non-default property values to |
| * streams (the default values are not saved). |
| * </p> |
| * <p> |
| * If a client sets a default value to be equivalent to the default-default for that |
| * type, the value is still known to the preference store as having a default value. |
| * That is, the name will still be returned in the result of the <code>defaultPropertyNames</code> |
| * and <code>contains</code> methods. |
| * </p> |
| * |
| * @since 2.0 |
| * @noextend This class is not intended to be subclassed by clients. |
| * @deprecated This class is replaced by {@link IEclipsePreferences}. Setting a default |
| * value is accomplished by a setting a value in the {@link DefaultScope}, and setting |
| * an explicit non-default value is accomplished by setting a value in the {@link InstanceScope}. |
| * To obtain a preference value, use the preference accessor methods on {@link IPreferencesService}. |
| */ |
| @Deprecated |
| public class Preferences { |
| |
| /** |
| * The default-default value for boolean properties (<code>false</code>). |
| */ |
| public static final boolean BOOLEAN_DEFAULT_DEFAULT = false; |
| |
| /** |
| * The default-default value for double properties (<code>0.0</code>). |
| */ |
| public static final double DOUBLE_DEFAULT_DEFAULT = 0.0; |
| |
| /** |
| * The default-default value for float properties (<code>0.0f</code>). |
| */ |
| public static final float FLOAT_DEFAULT_DEFAULT = 0.0f; |
| |
| /** |
| * The default-default value for int properties (<code>0</code>). |
| */ |
| public static final int INT_DEFAULT_DEFAULT = 0; |
| |
| /** |
| * The default-default value for long properties (<code>0L</code>). |
| */ |
| public static final long LONG_DEFAULT_DEFAULT = 0L; |
| |
| /** |
| * The default-default value for String properties (<code>""</code>). |
| */ |
| public static final String STRING_DEFAULT_DEFAULT = ""; //$NON-NLS-1$ |
| |
| /** |
| * The string representation used for <code>true</code> |
| * (<code>"true"</code>). |
| */ |
| protected static final String TRUE = "true"; //$NON-NLS-1$ |
| |
| /** |
| * The string representation used for <code>false</code> |
| * (<code>"false"</code>). |
| */ |
| protected static final String FALSE = "false"; //$NON-NLS-1$ |
| |
| /** |
| * Singleton empty string array (optimization) |
| */ |
| private static final String[] EMPTY_STRING_ARRAY = new String[0]; |
| |
| /** |
| * The simple identifier constant (value "<code>preferences</code>") of |
| * the extension point of the Core Runtime plug-in where plug-ins declare |
| * extensions to the preference facility. A plug-in may define any number |
| * of preference extensions. |
| * |
| * @since 3.2 |
| */ |
| public static final String PT_PREFERENCES = "preferences"; //$NON-NLS-1$ |
| |
| /** |
| * An event object describing a change to a named property. |
| * <p> |
| * The preferences object reports property change events for internal state |
| * changes that may be of interest to external parties. A special listener |
| * interface (<code>Preferences.IPropertyChangeListener</code>) is |
| * defined for this purpose. Listeners are registered via the |
| * <code>Preferences.addPropertyChangeListener</code> method. |
| * </p> |
| * <p> |
| * Clients cannot instantiate or subclass this class. |
| * </p> |
| * |
| * @see Preferences#addPropertyChangeListener(Preferences.IPropertyChangeListener) |
| * @see Preferences.IPropertyChangeListener |
| */ |
| public static class PropertyChangeEvent extends EventObject { |
| /** |
| * All serializable objects should have a stable serialVersionUID |
| */ |
| private static final long serialVersionUID = 1L; |
| |
| /** |
| * The name of the changed property. |
| */ |
| private String propertyName; |
| |
| /** |
| * The old value of the changed property, or <code>null</code> if |
| * not known or not relevant. |
| */ |
| private Object oldValue; |
| |
| /** |
| * The new value of the changed property, or <code>null</code> if |
| * not known or not relevant. |
| */ |
| private Object newValue; |
| |
| /** |
| * Creates a new property change event. |
| * |
| * @param source the object whose property has changed |
| * @param property the property that has changed (must not be |
| * <code>null</code>) |
| * @param oldValue the old value of the property, or |
| * <code>null</code> if none |
| * @param newValue the new value of the property, or |
| * <code>null</code> if none |
| */ |
| protected PropertyChangeEvent(Object source, String property, Object oldValue, Object newValue) { |
| |
| super(source); |
| if (property == null) { |
| throw new IllegalArgumentException(); |
| } |
| this.propertyName = property; |
| this.oldValue = oldValue; |
| this.newValue = newValue; |
| } |
| |
| /** |
| * Returns the name of the property that changed. |
| * <p> |
| * Warning: there is no guarantee that the property name returned |
| * is a constant string. Callers must compare property names using |
| * <code>equals</code>, not ==. |
| *</p> |
| * |
| * @return the name of the property that changed |
| */ |
| public String getProperty() { |
| return propertyName; |
| } |
| |
| /** |
| * Returns the new value of the property. |
| * |
| * @return the new value, or <code>null</code> if not known |
| * or not relevant |
| */ |
| public Object getNewValue() { |
| return newValue; |
| } |
| |
| /** |
| * Returns the old value of the property. |
| * |
| * @return the old value, or <code>null</code> if not known |
| * or not relevant |
| */ |
| public Object getOldValue() { |
| return oldValue; |
| } |
| } |
| |
| /** |
| * Listener for property changes. |
| * <p> |
| * Usage: |
| * <pre> |
| * Preferences.IPropertyChangeListener listener = |
| * new Preferences.IPropertyChangeListener() { |
| * public void propertyChange(Preferences.PropertyChangeEvent event) { |
| * ... // code to deal with occurrence of property change |
| * } |
| * }; |
| * emitter.addPropertyChangeListener(listener); |
| * ... |
| * emitter.removePropertyChangeListener(listener); |
| * </pre> |
| * </p> |
| * <p> |
| * <em>Note:</em> Depending on the means in which the property |
| * values changed, the old and new values for the property can |
| * be either typed, a string representation of the value, or <code>null</code>. |
| * Clients who wish to behave properly in all cases should all |
| * three cases in their implementation of the property change listener. |
| * </p> |
| */ |
| public interface IPropertyChangeListener extends EventListener { |
| |
| /** |
| * Notification that a property has changed. |
| * <p> |
| * This method gets called when the observed object fires a property |
| * change event. |
| * </p> |
| * |
| * @param event the property change event object describing which |
| * property changed and how |
| */ |
| public void propertyChange(Preferences.PropertyChangeEvent event); |
| } |
| |
| /** |
| * List of registered listeners (element type: |
| * <code>IPropertyChangeListener</code>). |
| * These listeners are to be informed when the current value of a property |
| * changes. |
| */ |
| protected ListenerList listeners = new ListenerList(); |
| |
| /** |
| * The mapping from property name to |
| * property value (represented as strings). |
| */ |
| private Properties properties; |
| |
| /** |
| * The mapping from property name to |
| * default property value (represented as strings); |
| * <code>null</code> if none. |
| */ |
| private Properties defaultProperties; |
| |
| /** |
| * Indicates whether a value has been changed by <code>setToDefault</code> |
| * or <code>setValue</code>; initially <code>false</code>. |
| */ |
| protected boolean dirty = false; |
| |
| /** |
| * Exports all non-default-valued preferences for all installed plugins to the |
| * provided file. If a file already exists at the given location, it will be deleted. |
| * If there are no preferences to export, no file will be written. |
| * <p> |
| * The file that is written can be read later using the importPreferences method. |
| * </p> |
| * @param path The absolute file system path of the file to export preferences to. |
| * @exception CoreException if this method fails. Reasons include: |
| * <ul> |
| * <li> The file could not be written.</li> |
| * </ul> |
| * @see #importPreferences(IPath) |
| * @see #validatePreferenceVersions(IPath) |
| */ |
| public static void exportPreferences(IPath path) throws CoreException { |
| File file = path.toFile(); |
| if (file.exists()) |
| file.delete(); |
| file.getParentFile().mkdirs(); |
| IPreferencesService service = PreferencesService.getDefault(); |
| OutputStream output = null; |
| FileOutputStream fos = null; |
| try { |
| fos = new FileOutputStream(file); |
| output = new BufferedOutputStream(fos); |
| IEclipsePreferences node = (IEclipsePreferences) service.getRootNode().node(InstanceScope.SCOPE); |
| service.exportPreferences(node, output, (String[]) null); |
| output.flush(); |
| fos.getFD().sync(); |
| } catch (IOException e) { |
| String message = NLS.bind(PrefsMessages.preferences_errorWriting, file, e.getMessage()); |
| IStatus status = new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, IStatus.ERROR, message, e); |
| throw new CoreException(status); |
| } finally { |
| if (output != null) |
| try { |
| output.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| } |
| |
| /** |
| * Loads the plugin preferences from the given file, and replaces all |
| * non-default-valued preferences for all plugins with the values from this file. |
| * <p> |
| * If the file contains preferences for plug-ins that don't exist in the current |
| * install, they are ignored. This method does not validate if the plug-in |
| * versions in the preference file match the currently installed plug-ins. |
| * Clients should first call validatePreferenceVersions on the file to ensure |
| * that the versions are compatible. |
| * </p> |
| * <p> |
| * The file must have been written by the exportPreferences method. |
| * </p> |
| * @param path The absolute file system path of the file to import preferences from. |
| * @exception CoreException if this method fails. Reasons include: |
| * <ul> |
| * <li> The file does not exist.</li> |
| * <li> The file could not be read.</li> |
| * </ul> |
| * @see #exportPreferences(IPath) |
| * @see #validatePreferenceVersions(IPath) |
| */ |
| public static void importPreferences(IPath path) throws CoreException { |
| if (!path.toFile().exists()) { |
| String msg = NLS.bind(PrefsMessages.preferences_fileNotFound, path.toOSString()); |
| throw new CoreException(new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, 1, msg, null)); |
| } |
| IPreferencesService service = PreferencesService.getDefault(); |
| InputStream input = null; |
| try { |
| input = new BufferedInputStream(new FileInputStream(path.toFile())); |
| service.importPreferences(input); |
| } catch (FileNotFoundException e) { |
| String msg = NLS.bind(PrefsMessages.preferences_fileNotFound, path.toOSString()); |
| throw new CoreException(new Status(IStatus.ERROR, PrefsMessages.OWNER_NAME, 1, msg, e)); |
| } finally { |
| if (input != null) |
| try { |
| input.close(); |
| } catch (IOException e) { |
| // ignore |
| } |
| } |
| } |
| |
| /** |
| * Validates that the preference versions in the given file match the versions |
| * of the currently installed plugins. Returns an OK status if all preferences match |
| * the currently installed plugins, otherwise a MultiStatus describing what |
| * plugins have preferences that don't match. |
| * <p> |
| * If the returned status has a <code>IStatus.WARNING</code> severity, |
| * it means that some preferences may not be applicable but for the most |
| * part they will be compatible. If the returned status has a |
| * <code>IStatus.ERROR</code> severity, it means that the preferences |
| * will probably not be compatible. |
| * <p> |
| * If the file contains preferences for plug-ins that don't exist in the current |
| * install, they are ignored. |
| * </p> |
| * <p> |
| * The file must have been written by the exportPreferences method. |
| * </p> |
| * @param file The absolute file system path of the preference file to validate. |
| * @see #exportPreferences(IPath) |
| * @see #importPreferences(IPath) |
| */ |
| public static IStatus validatePreferenceVersions(IPath file) { |
| PreferencesService service = PreferencesService.getDefault(); |
| return service.validateVersions(file); |
| } |
| |
| /** |
| * Creates an empty preference table. |
| * <p> |
| * Use the methods <code>load(InputStream)</code> and |
| * <code>store(InputStream)</code> to load and store these preferences. |
| * </p> |
| * @see #load(InputStream) |
| * @see #store(OutputStream, String) |
| */ |
| public Preferences() { |
| defaultProperties = new Properties(); |
| properties = new Properties(defaultProperties); |
| } |
| |
| /** |
| * Adds a property change listener to this preference object. |
| * Has no effect if the identical listener is already registered. |
| * <p> |
| * <em>Note:</em> Depending on the means in which the property |
| * values changed, the old and new values for the property can |
| * be either typed, a string representation of the value, or <code>null</code>. |
| * Clients who wish to behave properly in all cases should all |
| * three cases in their implementation of the property change listener. |
| * </p> |
| * @param listener a property change listener |
| */ |
| public void addPropertyChangeListener(IPropertyChangeListener listener) { |
| listeners.add(listener); |
| } |
| |
| /** |
| * Removes the given listener from this preference object. |
| * Has no effect if the listener is not registered. |
| * |
| * @param listener a property change listener |
| */ |
| public void removePropertyChangeListener(IPropertyChangeListener listener) { |
| listeners.remove(listener); |
| } |
| |
| /** |
| * Returns whether the given property is known to this preference object, |
| * either by having an explicit setting or by having a default |
| * setting. Returns <code>false</code> if the given name is <code>null</code>. |
| * |
| * @param name the name of the property, or <code>null</code> |
| * @return <code>true</code> if either a current value or a default |
| * value is known for the named property, and <code>false</code>otherwise |
| */ |
| public boolean contains(String name) { |
| return (properties.containsKey(name) || defaultProperties.containsKey(name)); |
| } |
| |
| /** |
| * Fires a property change event corresponding to a change to the |
| * current value of the property with the given name. |
| * |
| * @param name the name of the property, to be used as the property |
| * in the event object |
| * @param oldValue the old value, or <code>null</code> if not known or not |
| * relevant |
| * @param newValue the new value, or <code>null</code> if not known or not |
| * relevant |
| */ |
| protected void firePropertyChangeEvent(String name, Object oldValue, Object newValue) { |
| if (name == null) |
| throw new IllegalArgumentException(); |
| Object[] changeListeners = this.listeners.getListeners(); |
| // Do we even need to fire an event? |
| if (changeListeners.length == 0) |
| return; |
| final PropertyChangeEvent pe = new PropertyChangeEvent(this, name, oldValue, newValue); |
| for (int i = 0; i < changeListeners.length; ++i) { |
| final IPropertyChangeListener l = (IPropertyChangeListener) changeListeners[i]; |
| ISafeRunnable job = new ISafeRunnable() { |
| public void handleException(Throwable exception) { |
| // already being logged in SafeRunner#run() |
| } |
| |
| public void run() throws Exception { |
| l.propertyChange(pe); |
| } |
| }; |
| SafeRunner.run(job); |
| } |
| } |
| |
| /** |
| * Returns the current value of the boolean-valued property with the |
| * given name. |
| * Returns the default-default value (<code>false</code>) if there |
| * is no property with the given name, or if the current value |
| * cannot be treated as a boolean. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the boolean-valued property |
| */ |
| public boolean getBoolean(String name) { |
| String value = properties.getProperty(name); |
| if (value == null) { |
| return BOOLEAN_DEFAULT_DEFAULT; |
| } |
| return value.equals(Preferences.TRUE); |
| } |
| |
| /** |
| * Sets the current value of the boolean-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * A property change event is reported if the current value of the |
| * property actually changes from its previous value. In the event |
| * object, the property name is the name of the property, and the |
| * old and new values are wrapped as objects. |
| * </p> |
| * <p> |
| * If the given value is the same as the corresponding default value |
| * for the given property, the explicit setting is deleted. |
| * Note that the recommended way of re-initializing a property to its |
| * default value is to call <code>setToDefault</code>. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new current value of the property |
| */ |
| public void setValue(String name, boolean value) { |
| boolean defaultValue = getDefaultBoolean(name); |
| boolean oldValue = getBoolean(name); |
| if (value == defaultValue) { |
| Object removed = properties.remove(name); |
| if (removed != null) { |
| // removed an explicit setting |
| dirty = true; |
| } |
| } else { |
| properties.put(name, value ? Preferences.TRUE : Preferences.FALSE); |
| } |
| if (oldValue != value) { |
| // mark as dirty since value did really change |
| dirty = true; |
| // report property change if getValue now returns different value |
| firePropertyChangeEvent(name, oldValue ? Boolean.TRUE : Boolean.FALSE, value ? Boolean.TRUE : Boolean.FALSE); |
| } |
| } |
| |
| /** |
| * Returns the default value for the boolean-valued property |
| * with the given name. |
| * Returns the default-default value (<code>false</code>) if there |
| * is no default property with the given name, or if the default |
| * value cannot be treated as a boolean. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the default value of the named property |
| */ |
| public boolean getDefaultBoolean(String name) { |
| String value = defaultProperties.getProperty(name); |
| if (value == null) { |
| return BOOLEAN_DEFAULT_DEFAULT; |
| } |
| return value.equals(Preferences.TRUE); |
| } |
| |
| /** |
| * Sets the default value for the boolean-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * Note that the current value of the property is affected if |
| * the property's current value was its old default value, in which |
| * case it changes to the new default value. If the property's current |
| * is different from its old default value, its current value is |
| * unaffected. No property change events are reported by changing default |
| * values. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new default value for the property |
| */ |
| public void setDefault(String name, boolean value) { |
| defaultProperties.put(name, value ? Preferences.TRUE : Preferences.FALSE); |
| } |
| |
| /** |
| * Returns the current value of the double-valued property with the |
| * given name. |
| * Returns the default-default value (<code>0.0</code>) if there |
| * is no property with the given name, or if the current value |
| * cannot be treated as a double. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the double-valued property |
| */ |
| public double getDouble(String name) { |
| return convertToDouble(properties.getProperty(name), DOUBLE_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the current value of the double-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * A property change event is reported if the current value of the |
| * property actually changes from its previous value. In the event |
| * object, the property name is the name of the property, and the |
| * old and new values are wrapped as objects. |
| * </p> |
| * <p> |
| * If the given value is the same as the corresponding default value |
| * for the given property, the explicit setting is deleted. |
| * Note that the recommended way of re-initializing a property to its |
| * default value is to call <code>setToDefault</code>. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new current value of the property; must be |
| * a number (not a NaN) |
| */ |
| public void setValue(String name, double value) { |
| if (Double.isNaN(value)) { |
| throw new IllegalArgumentException(); |
| } |
| double defaultValue = getDefaultDouble(name); |
| double oldValue = getDouble(name); |
| if (value == defaultValue) { |
| Object removed = properties.remove(name); |
| if (removed != null) { |
| // removed an explicit setting |
| dirty = true; |
| } |
| } else { |
| properties.put(name, Double.toString(value)); |
| } |
| if (oldValue != value) { |
| // mark as dirty since value did really change |
| dirty = true; |
| // report property change if getValue now returns different value |
| firePropertyChangeEvent(name, new Double(oldValue), new Double(value)); |
| } |
| } |
| |
| /** |
| * Returns the default value for the double-valued property |
| * with the given name. |
| * Returns the default-default value (<code>0.0</code>) if there |
| * is no default property with the given name, or if the default |
| * value cannot be treated as a double. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the default value of the named property |
| */ |
| public double getDefaultDouble(String name) { |
| return convertToDouble(defaultProperties.getProperty(name), DOUBLE_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the default value for the double-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * Note that the current value of the property is affected if |
| * the property's current value was its old default value, in which |
| * case it changes to the new default value. If the property's current |
| * is different from its old default value, its current value is |
| * unaffected. No property change events are reported by changing default |
| * values. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new default value for the property; must be |
| * a number (not a NaN) |
| */ |
| public void setDefault(String name, double value) { |
| if (Double.isNaN(value)) { |
| throw new IllegalArgumentException(); |
| } |
| defaultProperties.put(name, Double.toString(value)); |
| } |
| |
| /** |
| * Converts the given raw property value string to a double. |
| * |
| * @param rawPropertyValue the raw property value, or <code>null</code> |
| * if none |
| * @param defaultValue the default value |
| * @return the raw value converted to a double, or the given |
| * <code>defaultValue</code> if the raw value is <code>null</code> or |
| * cannot be parsed as a double |
| */ |
| private double convertToDouble(String rawPropertyValue, double defaultValue) { |
| double result = defaultValue; |
| if (rawPropertyValue != null) { |
| try { |
| result = Double.parseDouble(rawPropertyValue); |
| } catch (NumberFormatException e) { |
| // raw value cannot be treated as one of these |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the current value of the float-valued property with the |
| * given name. |
| * Returns the default-default value (<code>0.0f</code>) if there |
| * is no property with the given name, or if the current value |
| * cannot be treated as a float. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the float-valued property |
| */ |
| public float getFloat(String name) { |
| return convertToFloat(properties.getProperty(name), FLOAT_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the current value of the float-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * A property change event is reported if the current value of the |
| * property actually changes from its previous value. In the event |
| * object, the property name is the name of the property, and the |
| * old and new values are wrapped as objects. |
| * </p> |
| * <p> |
| * If the given value is the same as the corresponding default value |
| * for the given property, the explicit setting is deleted. |
| * Note that the recommended way of re-initializing a property to its |
| * default value is to call <code>setToDefault</code>. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new current value of the property; must be |
| * a number (not a NaN) |
| */ |
| public void setValue(String name, float value) { |
| if (Float.isNaN(value)) { |
| throw new IllegalArgumentException(); |
| } |
| float defaultValue = getDefaultFloat(name); |
| float oldValue = getFloat(name); |
| if (value == defaultValue) { |
| Object removed = properties.remove(name); |
| if (removed != null) { |
| // removed an explicit setting |
| dirty = true; |
| } |
| } else { |
| properties.put(name, Float.toString(value)); |
| } |
| if (oldValue != value) { |
| // mark as dirty since value did really change |
| dirty = true; |
| // report property change if getValue now returns different value |
| firePropertyChangeEvent(name, new Float(oldValue), new Float(value)); |
| } |
| } |
| |
| /** |
| * Returns the default value for the float-valued property |
| * with the given name. |
| * Returns the default-default value (<code>0.0f</code>) if there |
| * is no default property with the given name, or if the default |
| * value cannot be treated as a float. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the default value of the named property |
| */ |
| public float getDefaultFloat(String name) { |
| return convertToFloat(defaultProperties.getProperty(name), FLOAT_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the default value for the float-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * Note that the current value of the property is affected if |
| * the property's current value was its old default value, in which |
| * case it changes to the new default value. If the property's current |
| * is different from its old default value, its current value is |
| * unaffected. No property change events are reported by changing default |
| * values. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new default value for the property; must be |
| * a number (not a NaN) |
| */ |
| public void setDefault(String name, float value) { |
| if (Float.isNaN(value)) { |
| throw new IllegalArgumentException(); |
| } |
| defaultProperties.put(name, Float.toString(value)); |
| } |
| |
| /** |
| * Converts the given raw property value string to a float. |
| * |
| * @param rawPropertyValue the raw property value, or <code>null</code> |
| * if none |
| * @param defaultValue the default value |
| * @return the raw value converted to a float, or the given |
| * <code>defaultValue</code> if the raw value is <code>null</code> or |
| * cannot be parsed as a float |
| */ |
| private float convertToFloat(String rawPropertyValue, float defaultValue) { |
| float result = defaultValue; |
| if (rawPropertyValue != null) { |
| try { |
| result = Float.parseFloat(rawPropertyValue); |
| } catch (NumberFormatException e) { |
| // raw value cannot be treated as one of these |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the current value of the integer-valued property with the |
| * given name. |
| * Returns the default-default value (<code>0</code>) if there |
| * is no property with the given name, or if the current value |
| * cannot be treated as an integer. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the int-valued property |
| */ |
| public int getInt(String name) { |
| return convertToInt(properties.getProperty(name), INT_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the current value of the integer-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * A property change event is reported if the current value of the |
| * property actually changes from its previous value. In the event |
| * object, the property name is the name of the property, and the |
| * old and new values are wrapped as objects. |
| * </p> |
| * <p> |
| * If the given value is the same as the corresponding default value |
| * for the given property, the explicit setting is deleted. |
| * Note that the recommended way of re-initializing a property to its |
| * default value is to call <code>setToDefault</code>. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new current value of the property |
| */ |
| public void setValue(String name, int value) { |
| int defaultValue = getDefaultInt(name); |
| int oldValue = getInt(name); |
| if (value == defaultValue) { |
| Object removed = properties.remove(name); |
| if (removed != null) { |
| // removed an explicit setting |
| dirty = true; |
| } |
| } else { |
| properties.put(name, Integer.toString(value)); |
| } |
| if (oldValue != value) { |
| // mark as dirty since value did really change |
| dirty = true; |
| // report property change if getValue now returns different value |
| firePropertyChangeEvent(name, new Integer(oldValue), new Integer(value)); |
| } |
| } |
| |
| /** |
| * Returns the default value for the integer-valued property |
| * with the given name. |
| * Returns the default-default value (<code>0</code>) if there |
| * is no default property with the given name, or if the default |
| * value cannot be treated as an integer. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the default value of the named property |
| */ |
| public int getDefaultInt(String name) { |
| return convertToInt(defaultProperties.getProperty(name), INT_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the default value for the integer-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * Note that the current value of the property is affected if |
| * the property's current value was its old default value, in which |
| * case it changes to the new default value. If the property's current |
| * is different from its old default value, its current value is |
| * unaffected. No property change events are reported by changing default |
| * values. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new default value for the property |
| */ |
| public void setDefault(String name, int value) { |
| defaultProperties.put(name, Integer.toString(value)); |
| } |
| |
| /** |
| * Converts the given raw property value string to an int. |
| * |
| * @param rawPropertyValue the raw property value, or <code>null</code> |
| * if none |
| * @param defaultValue the default value |
| * @return the raw value converted to an int, or the given |
| * <code>defaultValue</code> if the raw value is <code>null</code> or |
| * cannot be parsed as an int |
| */ |
| private int convertToInt(String rawPropertyValue, int defaultValue) { |
| int result = defaultValue; |
| if (rawPropertyValue != null) { |
| try { |
| result = Integer.parseInt(rawPropertyValue); |
| } catch (NumberFormatException e) { |
| // raw value cannot be treated as one of these |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the current value of the long-valued property with the |
| * given name. |
| * Returns the default-default value (<code>0L</code>) if there |
| * is no property with the given name, or if the current value |
| * cannot be treated as a long. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the long-valued property |
| */ |
| public long getLong(String name) { |
| return convertToLong(properties.getProperty(name), LONG_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the current value of the long-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * A property change event is reported if the current value of the |
| * property actually changes from its previous value. In the event |
| * object, the property name is the name of the property, and the |
| * old and new values are wrapped as objects. |
| * </p> |
| * <p> |
| * If the given value is the same as the corresponding default value |
| * for the given property, the explicit setting is deleted. |
| * Note that the recommended way of re-initializing a property to its |
| * default value is to call <code>setToDefault</code>. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new current value of the property |
| */ |
| public void setValue(String name, long value) { |
| long defaultValue = getDefaultLong(name); |
| long oldValue = getLong(name); |
| if (value == defaultValue) { |
| Object removed = properties.remove(name); |
| if (removed != null) { |
| // removed an explicit setting |
| dirty = true; |
| } |
| } else { |
| properties.put(name, Long.toString(value)); |
| } |
| if (oldValue != value) { |
| // mark as dirty since value did really change |
| dirty = true; |
| // report property change if getValue now returns different value |
| firePropertyChangeEvent(name, new Long(oldValue), new Long(value)); |
| } |
| } |
| |
| /** |
| * Returns the default value for the long-valued property |
| * with the given name. |
| * Returns the default-default value (<code>0L</code>) if there |
| * is no default property with the given name, or if the default |
| * value cannot be treated as a long. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the default value of the named property |
| */ |
| public long getDefaultLong(String name) { |
| return convertToLong(defaultProperties.getProperty(name), LONG_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the default value for the long-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * Note that the current value of the property is affected if |
| * the property's current value was its old default value, in which |
| * case it changes to the new default value. If the property's current |
| * is different from its old default value, its current value is |
| * unaffected. No property change events are reported by changing default |
| * values. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new default value for the property |
| */ |
| public void setDefault(String name, long value) { |
| defaultProperties.put(name, Long.toString(value)); |
| } |
| |
| /** |
| * Converts the given raw property value string to a long. |
| * |
| * @param rawPropertyValue the raw property value, or <code>null</code> |
| * if none |
| * @param defaultValue the default value |
| * @return the raw value converted to a long, or the given |
| * <code>defaultValue</code> if the raw value is <code>null</code> or |
| * cannot be parsed as a long |
| */ |
| private long convertToLong(String rawPropertyValue, long defaultValue) { |
| long result = defaultValue; |
| if (rawPropertyValue != null) { |
| try { |
| result = Long.parseLong(rawPropertyValue); |
| } catch (NumberFormatException e) { |
| // raw value cannot be treated as one of these |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Returns the current value of the string-valued property with the |
| * given name. |
| * Returns the default-default value (the empty string <code>""</code>) |
| * if there is no property with the given name. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the string-valued property |
| */ |
| public String getString(String name) { |
| String value = properties.getProperty(name); |
| return (value != null ? value : STRING_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the current value of the string-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * A property change event is reported if the current value of the |
| * property actually changes from its previous value. In the event |
| * object, the property name is the name of the property, and the |
| * old and new values are wrapped as objects. |
| * </p> |
| * <p> |
| * If the given value is the same as the corresponding default value |
| * for the given property, the explicit setting is deleted. |
| * Note that the recommended way of re-initializing a property to its |
| * default value is to call <code>setToDefault</code>. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new current value of the property |
| */ |
| public void setValue(String name, String value) { |
| if (value == null) { |
| throw new IllegalArgumentException(); |
| } |
| String defaultValue = getDefaultString(name); |
| String oldValue = getString(name); |
| if (value.equals(defaultValue)) { |
| Object removed = properties.remove(name); |
| if (removed != null) { |
| // removed an explicit setting |
| dirty = true; |
| } |
| } else { |
| properties.put(name, value); |
| } |
| if (!oldValue.equals(value)) { |
| // mark as dirty since value did really change |
| dirty = true; |
| // report property change if getValue now returns different value |
| firePropertyChangeEvent(name, oldValue, value); |
| } |
| } |
| |
| /** |
| * Returns the default value for the string-valued property |
| * with the given name. |
| * Returns the default-default value (the empty string <code>""</code>) |
| * is no default property with the given name, or if the default |
| * value cannot be treated as a string. |
| * The given name must not be <code>null</code>. |
| * |
| * @param name the name of the property |
| * @return the default value of the named property |
| */ |
| public String getDefaultString(String name) { |
| String value = defaultProperties.getProperty(name); |
| return (value != null ? value : STRING_DEFAULT_DEFAULT); |
| } |
| |
| /** |
| * Sets the default value for the string-valued property with the |
| * given name. The given name must not be <code>null</code>. |
| * <p> |
| * Note that the current value of the property is affected if |
| * the property's current value was its old default value, in which |
| * case it changes to the new default value. If the property's current |
| * is different from its old default value, its current value is |
| * unaffected. No property change events are reported by changing default |
| * values. |
| * </p> |
| * |
| * @param name the name of the property |
| * @param value the new default value for the property |
| */ |
| public void setDefault(String name, String value) { |
| if (value == null) { |
| throw new IllegalArgumentException(); |
| } |
| defaultProperties.put(name, value); |
| } |
| |
| /** |
| * Returns whether the property with the given name has the default value in |
| * virtue of having no explicitly set value. |
| * Returns <code>false</code> if the given name is <code>null</code>. |
| * |
| * @param name the name of the property, or <code>null</code> |
| * @return <code>true</code> if the property has no explicitly set value, |
| * and <code>false</code> otherwise (including the case where the property |
| * is unknown to this object) |
| */ |
| public boolean isDefault(String name) { |
| return !properties.containsKey(name); |
| } |
| |
| /** |
| * Sets the current value of the property with the given name back |
| * to its default value. Has no effect if the property does not have |
| * its own current value. The given name must not be <code>null</code>. |
| * <p> |
| * Note that the recommended way of re-initializing a property to the |
| * appropriate default value is to call <code>setToDefault</code>. |
| * This is implemented by removing the named value from the object, |
| * thereby exposing the default value. |
| * </p> |
| * <p> |
| * A property change event is always reported. In the event |
| * object, the property name is the name of the property, and the |
| * old and new values are either strings, or <code>null</code> |
| * indicating the default-default value. |
| * </p> |
| * |
| * @param name the name of the property |
| */ |
| public void setToDefault(String name) { |
| Object oldPropertyValue = properties.remove(name); |
| if (oldPropertyValue != null) { |
| dirty = true; |
| } |
| String newValue = defaultProperties.getProperty(name, null); |
| // n.b. newValue == null if there is no default value |
| // can't determine correct default-default without knowing type |
| firePropertyChangeEvent(name, oldPropertyValue, newValue); |
| } |
| |
| /** |
| * Returns a list of all properties known to this preference object which |
| * have current values other than their default value. |
| * |
| * @return an array of property names |
| */ |
| public String[] propertyNames() { |
| return properties.keySet().toArray(EMPTY_STRING_ARRAY); |
| } |
| |
| /** |
| * Returns a list of all properties known to this preference object which |
| * have an explicit default value set. |
| * |
| * @return an array of property names |
| */ |
| public String[] defaultPropertyNames() { |
| return defaultProperties.keySet().toArray(EMPTY_STRING_ARRAY); |
| } |
| |
| /** |
| * Returns whether the current values in this preference object |
| * require saving. |
| * |
| * @return <code>true</code> if at least one of the properties |
| * known to this preference object has a current value different from its |
| * default value, and <code>false</code> otherwise |
| */ |
| public boolean needsSaving() { |
| return dirty; |
| } |
| |
| /** |
| * Saves the non-default-valued properties known to this preference object to |
| * the given output stream using |
| * <code>Properties.store(OutputStream,String)</code>. |
| * <p> |
| * Note that the output is unconditionally written, even when |
| * <code>needsSaving</code> is <code>false</code>. |
| * </p> |
| * |
| * @param out the output stream |
| * @param header a comment to be included in the output, or |
| * <code>null</code> if none |
| * @exception IOException if there is a problem saving this preference object |
| * @see Properties#store(OutputStream,String) |
| */ |
| public void store(OutputStream out, String header) throws IOException { |
| properties.store(out, header); |
| dirty = false; |
| } |
| |
| /** |
| * Loads the non-default-valued properties for this preference object from the |
| * given input stream using |
| * <code>java.util.Properties.load(InputStream)</code>. Default property |
| * values are not affected. |
| * |
| * @param in the input stream |
| * @exception IOException if there is a problem loading this preference |
| * object |
| * @see java.util.Properties#load(InputStream) |
| */ |
| public void load(InputStream in) throws IOException { |
| properties.load(in); |
| dirty = false; |
| } |
| } |