diff --git a/core/java/src/net/i2p/I2PAppContext.java b/core/java/src/net/i2p/I2PAppContext.java index b497796408cb2b6051d9386c3ed7dd230bf82c31..4b023034b83be8dcdbb8a1f04440e0c98253777e 100644 --- a/core/java/src/net/i2p/I2PAppContext.java +++ b/core/java/src/net/i2p/I2PAppContext.java @@ -27,11 +27,13 @@ import net.i2p.util.Clock; import net.i2p.util.ConcurrentHashSet; import net.i2p.util.FileUtil; import net.i2p.util.FortunaRandomSource; +import net.i2p.util.I2PProperties; import net.i2p.util.KeyRing; import net.i2p.util.LogManager; //import net.i2p.util.PooledRandomSource; import net.i2p.util.RandomSource; import net.i2p.util.SecureDirectory; +import net.i2p.util.I2PProperties.I2PPropertyCallback; /** * <p>Provide a base scope for accessing singletons that I2P exposes. Rather than @@ -62,7 +64,7 @@ public class I2PAppContext { /** the context that components without explicit root are bound */ protected static I2PAppContext _globalAppContext; - private Properties _overrideProps; + private I2PProperties _overrideProps; private StatManager _statManager; private SessionKeyManager _sessionKeyManager; @@ -165,7 +167,7 @@ public class I2PAppContext { _globalAppContext = this; } } - _overrideProps = envProps; + _overrideProps = new I2PProperties(envProps); _statManager = null; _sessionKeyManager = null; _namingService = null; @@ -478,6 +480,27 @@ public class I2PAppContext { return names; } + /** + * Modify the configuration attributes of this context, changing + * one of the properties provided during the context construction. + * @param propName The name of the property. + * @param value The new value for the property. + */ + public void setProperty(String propName, String value) { + if(_overrideProps != null) { + _overrideProps.setProperty(propName, value); + } + } + + /** + * Add a callback, which will fire upon changes in the property + * given in the specific callback. + * @param callback The implementation of the callback. + */ + public void addPropertyCallback(I2PPropertyCallback callback) { + _overrideProps.addCallBack(callback); + } + /** * The statistics component with which we can track various events * over time. diff --git a/core/java/src/net/i2p/util/I2PProperties.java b/core/java/src/net/i2p/util/I2PProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..b6dfca8a165147aa8f0d9e02b3fbea00bf703d0f --- /dev/null +++ b/core/java/src/net/i2p/util/I2PProperties.java @@ -0,0 +1,57 @@ +package net.i2p.util; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.concurrent.CopyOnWriteArrayList; + +/** + * This class contains a number of properties ((key,value)-pairs). + * Additionally, it adds the possibility for callbacks, + * to allow immediate response to changing properties. + * @author Mathiasdm + * + */ +public class I2PProperties extends Properties { + + /** + * Keep a list of callbacks to contact the interested parties + * that want to know about property changes. + * @todo Use a map of lists, so we don't need to loop over all the callbacks on every change. + */ + private final List<I2PPropertyCallback> _callbacks = new CopyOnWriteArrayList<I2PPropertyCallback>(); + + public I2PProperties() { + super(); + } + + public I2PProperties(Properties defaults) { + super(defaults); + } + + public void addCallBack(I2PPropertyCallback callback) { + _callbacks.add(callback); + } + + public void removeCallBack(I2PPropertyCallback callback) { + _callbacks.remove(callback); + } + + public Object setProperty(String key, String value) { + Object returnValue = super.setProperty(key, value); + for(I2PPropertyCallback callback: _callbacks) { + if(callback.getPropertyKey().equals(key)) { + callback.propertyChanged(key, value); + } + } + return returnValue; + } + + public interface I2PPropertyCallback { + + public void propertyChanged(String key, String value); + + public String getPropertyKey(); + } + +}