// ObservableProperties.java
// $Id: ObservableProperties.java,v 1.8 2000/08/16 21:37:58 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html
import java.io.File;
import java.util.Properties;
import java.util.StringTokenizer;
/**
* An enhanced property class that provides support to monitor changes. This
* class extends the basic properties class of Java, by providing monitoring
* support. It also provides more type conversion.
*
* @see PropertyMonitoring
*/
public class ObservableProperties extends Properties {
private static final boolean debug = false;
PropertyMonitoring observers[] = null;
int observers_count = 0;
/**
* Subscribe for property monitoring.
*
* @param observer
* The object that handles the PropertyMonitoring interface.
*/
public synchronized void registerObserver(PropertyMonitoring o) {
// Try looking for an empty slot:
for (int i = 0; i < observers.length; i++) {
if (observers[i] == null) {
observers[i] = o;
return;
}
}
// Add the observer to the registered oned, resizing array if needed
if (observers_count + 1 >= observers.length) {
PropertyMonitoring m[] = new PropertyMonitoring[observers.length * 2];
System.arraycopy(observers, 0, m, 0, observers.length);
observers = m;
}
observers[observers_count++] = o;
}
/**
* Unsubscribe this object from the observers list.
*
* @param observer
* The observer to unsubscribe.
* @return A boolean <strong>true</strong> if object was succesfully
* unsubscribed, <strong>false</strong> otherwise.
*/
public synchronized boolean unregisterObserver(PropertyMonitoring o) {
for (int i = 0; i < observers.length; i++) {
if (observers[i] == o) {
observers[i] = null;
return true;
}
}
return false;
}
/**
* Update a property value. Assign a value to a property. If the property
* value has really changed notify our observers of the change.
*
* @param name
* The name of the property to assign.
* @param value
* The new value for this property, or <strong>null</strong> if the
* property setting is to be cancelled.
* @return A boolean <strong>true</strong> if change was accepted by our
* observers, <strong>false</strong> otherwise.
*/
public synchronized boolean putValue(String name, String value) {
if (debug)
System.out.println("ObservableProperties: put " + name + "=[" + value + "]");
// If null value, remove the prop definition:
if (value == null) {
super.remove(name);
return true;
}
// Otherwise, proceed:
String old = (String) get(name);
if ((old == null) || (!old.equals(value))) {
super.put(name, value);
for (int i = 0; i < observers.length; i++) {
if (observers[i] == null)
continue;
if (debug)
System.out.println("ObservableProperties: notifies " + observers[i]);
if (!observers[i].propertyChanged(name)) {
if (old != null)
super.put(name, old);
return false;
}
}
}
return true;
}
/**
* Get this property value, as a boolean.
*
* @param name
* The name of the property to be fetched.
* @param def
* The default value, if the property isn't defined.
* @return A Boolean instance.
*/
public boolean getBoolean(String name, boolean def) {
String v = getProperty(name, null);
if (v != null)
return "true".equalsIgnoreCase(v) ? true : false;
return def;
}
/**
* Get this property value, as a String.
*
* @param name
* The name of the property to be fetched.
* @param def
* The default value, if the property isn't defined.
* @return An instance of String.
*/
public String getString(String name, String def) {
String v = getProperty(name, null);
if (v != null)
return v;
return def;
}
/**
* Get this property as a String array. By convention, properties that are get
* as string arrays should be encoded as a <strong>|</strong> separated list
* of Strings.
*
* @param name
* The property's name.
* @param def
* The default value (if undefined).
* @return A String array, or <strong>null</strong> if the property is
* undefined.
*/
public String[] getStringArray(String name, String def[]) {
String v = getProperty(name, null);
if (v == null)
return def;
// Parse the property value:
StringTokenizer st = new StringTokenizer(v, "|");
int len = st.countTokens();
String ret[] = new String[len];
for (int i = 0; i < ret.length; i++) {
ret[i] = st.nextToken();
}
return ret;
}
/**
* Get this property value, as an integer.
*
* @param name
* The name of the property to be fetched.
* @param def
* The default value, if the property isn't defined.
* @return An integer value.
*/
public int getInteger(String name, int def) {
String v = getProperty(name, null);
if (v != null) {
try {
if (v.startsWith("0x")) {
return Integer.valueOf(v.substring(2), 16).intValue();
}
if (v.startsWith("#")) {
return Integer.valueOf(v.substring(1), 16).intValue();
}
return Integer.valueOf(v).intValue();
} catch (NumberFormatException e) {
}
}
return def;
}
public long getLong(String name, long def) {
String v = getProperty(name, null);
if (v != null) {
try {
return Long.valueOf(v).longValue();
} catch (NumberFormatException e) {
}
}
return def;
}
/**
* Get this property value, as a double.
*
* @param name
* The name of the property.
* @param def
* The default value if undefined.
* @return A double value.
*/
public double getDouble(String name, double def) {
String v = getProperty(name, null);
if (v != null) {
try {
return Double.valueOf(v).doubleValue();
} catch (NumberFormatException ex) {
}
}
return def;
}
/**
* Get this property value, as a File.
*
* @param name
* The name of the property to be fetched.
* @param def
* The default value, if the property isn't defined.
* @return An instance of File.
*/
public File getFile(String name, File def) {
String v = getProperty(name, null);
if (v != null)
return new File(v);
return def;
}
/**
* Build an httpdProperties instance from a Properties instance.
*
* @param props
* The Properties instance.
*/
public ObservableProperties(Properties props) {
super(props);
this.observers = new PropertyMonitoring[5];
this.observers_count = 0;
}
}
// PropertyMonitoring.java
// $Id: PropertyMonitoring.java,v 1.3 2000/08/16 21:37:58 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html
interface PropertyMonitoring {
/**
* The callback method, invoked when any property change occurs.
*
* @param name
* The name of the property that changed.
* @return A boolean, if <strong>true</strong>, accept the new property
* value, otherwise, reject it and reset the property to its old
* value.
*/
public boolean propertyChanged(String name);
}
|