You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2006/04/16 19:55:57 UTC
svn commit: r394529 -
/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/
Author: oheger
Date: Sun Apr 16 10:55:55 2006
New Revision: 394529
URL: http://svn.apache.org/viewcvs?rev=394529&view=rev
Log:
Added event listener support to basic configuration classes
Modified:
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/BaseConfiguration.java
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java?rev=394529&r1=394528&r2=394529&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractConfiguration.java Sun Apr 16 10:55:55 2006
@@ -26,12 +26,32 @@
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.iterators.FilterIterator;
+import org.apache.commons.configuration.event.EventSource;
import org.apache.commons.lang.BooleanUtils;
/**
- * Abstract configuration class. Provide basic functionality but does not store
- * any data. If you want to write your own Configuration class then you should
- * implement only abstract methods from this class.
+ * <p>Abstract configuration class. Provides basic functionality but does not
+ * store any data.</p>
+ * <p>If you want to write your own Configuration class then you should
+ * implement only abstract methods from this class. A lot of functionality
+ * needed by typical implementations of the <code>Configuration</conde>
+ * interface is already provided by this base class. Following is a list of
+ * feauters implemented here:
+ * <ul><li>Data conversion support. The various data types required by the
+ * <code>Configuration</code> interface are already handled by this base class.
+ * A concrete sub class only needs to provide a generic <code>getProperty()</code>
+ * method.</li>
+ * <li>Support for variable interpolation. Property values containing special
+ * variable tokens (like <code>${var}</code>) will be replaced by their
+ * corresponding values.</li>
+ * <li>Support for string lists. The values of properties to be added to this
+ * configuration are checked whether they contain a list delimiter character. If
+ * this is the case and if list splitting is enabled, the string is splitted and
+ * multiple values are added for this property.</li>
+ * <li>Basic event support. Whenever this configuration is modified registered
+ * event listeners are notified. Refer to the various <code>EVENT_XXX</code>
+ * constants to get an impression about which event types are supported.</li>
+ * </ul></p>
*
* @author <a href="mailto:ksh@scand.com">Konstantin Shaposhnikov </a>
* @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger </a>
@@ -39,8 +59,20 @@
* @version $Id: AbstractConfiguration.java,v 1.29 2004/12/02 22:05:52 ebourg
* Exp $
*/
-public abstract class AbstractConfiguration implements Configuration
+public abstract class AbstractConfiguration extends EventSource implements Configuration
{
+ /** Constant for the add property event type.*/
+ public static final int EVENT_ADD_PROPERTY = 1;
+
+ /** Constant for the clear property event type.*/
+ public static final int EVENT_CLEAR_PROPERTY = 2;
+
+ /** Constant for the set property event type.*/
+ public static final int EVENT_SET_PROPERTY = 3;
+
+ /** Constant for the clear configuration event type.*/
+ public static final int EVENT_CLEAR = 4;
+
/** start token */
protected static final String START_TOKEN = "${";
@@ -187,6 +219,8 @@
*/
public void addProperty(String key, Object value)
{
+ fireEvent(EVENT_ADD_PROPERTY, key, value, true);
+
if (!isDelimiterParsingDisabled())
{
Iterator it = PropertyConverter.toIterator(value, getListDelimiter());
@@ -199,6 +233,8 @@
{
addPropertyDirect(key, value);
}
+
+ fireEvent(EVENT_ADD_PROPERTY, key, value, false);
}
/**
@@ -279,32 +315,74 @@
*/
public void setProperty(String key, Object value)
{
- clearProperty(key);
- addProperty(key, value);
+ fireEvent(EVENT_SET_PROPERTY, key, value, true);
+ setDetailEvents(false);
+ try
+ {
+ clearProperty(key);
+ addProperty(key, value);
+ }
+ finally
+ {
+ setDetailEvents(true);
+ }
+ fireEvent(EVENT_SET_PROPERTY, key, value, false);
}
/**
- * {@inheritDoc}
+ * Removes the specified property from this configuration. This
+ * implementation performs some preparations and then delegates to
+ * <code>clearPropertyDirect()</code>, which will do the real work.
+ *
+ * @param key the key to be removed
*/
- public abstract void clearProperty(String key);
+ public void clearProperty(String key)
+ {
+ fireEvent(EVENT_CLEAR_PROPERTY, key, null, true);
+ clearPropertyDirect(key);
+ fireEvent(EVENT_CLEAR_PROPERTY, key, null, false);
+ }
+
+ /**
+ * Removes the specified property from this configuration. This method is
+ * called by <code>clearProperty()</code> after it has done some
+ * preparations. It should be overriden in sub classes. This base
+ * implementation is just left empty.
+ *
+ * @param key the key to be removed
+ */
+ protected void clearPropertyDirect(String key)
+ {
+ // override in sub classes
+ }
/**
* {@inheritDoc}
*/
public void clear()
{
- Iterator it = getKeys();
- while (it.hasNext())
+ fireEvent(EVENT_CLEAR, null, null, true);
+ setDetailEvents(false);
+ try
{
- String key = (String) it.next();
- it.remove();
-
- if (containsKey(key))
+ Iterator it = getKeys();
+ while (it.hasNext())
{
- // workaround for Iterators that do not remove the property on calling remove()
- clearProperty(key);
+ String key = (String) it.next();
+ it.remove();
+
+ if (containsKey(key))
+ {
+ // workaround for Iterators that do not remove the property on calling remove()
+ clearProperty(key);
+ }
}
}
+ finally
+ {
+ setDetailEvents(true);
+ }
+ fireEvent(EVENT_CLEAR, null, null, false);
}
/**
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java?rev=394529&r1=394528&r2=394529&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java Sun Apr 16 10:55:55 2006
@@ -76,6 +76,9 @@
*/
public abstract class AbstractFileConfiguration extends BaseConfiguration implements FileConfiguration
{
+ /** Constant for the configuration reload event.*/
+ public static final int EVENT_RELOAD = 20;
+
/** Stores the file name.*/
protected String fileName;
@@ -709,8 +712,18 @@
if (strategy.reloadingRequired())
{
- clear();
- load();
+ fireEvent(EVENT_RELOAD, null, getURL(), true);
+ setDetailEvents(false);
+ try
+ {
+ clear();
+ load();
+ }
+ finally
+ {
+ setDetailEvents(true);
+ }
+ fireEvent(EVENT_RELOAD, null, getURL(), false);
// notify the strategy
strategy.reloadingPerformed();
@@ -760,6 +773,31 @@
{
noReload--;
}
+ }
+ }
+
+ /**
+ * Sends an event to all registered listeners. This implementation ensures
+ * that no reloads are performed while the listeners are invoked. So
+ * infinite loops can be avoided that can be caused by event listeners
+ * accessing the configuration's properties when they are invoked.
+ *
+ * @param type the event type
+ * @param propName the name of the property
+ * @param propValue the value of the property
+ * @param before the before update flag
+ */
+ protected void fireEvent(int type, String propName, Object propValue,
+ boolean before)
+ {
+ enterNoReload();
+ try
+ {
+ super.fireEvent(type, propName, propValue, before);
+ }
+ finally
+ {
+ exitNoReload();
}
}
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java?rev=394529&r1=394528&r2=394529&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java Sun Apr 16 10:55:55 2006
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 The Apache Software Foundation.
+ * Copyright 2005-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
@@ -24,6 +24,8 @@
import java.net.URL;
import java.util.Iterator;
+import org.apache.commons.configuration.event.ConfigurationEvent;
+import org.apache.commons.configuration.event.ConfigurationListener;
import org.apache.commons.configuration.reloading.ReloadingStrategy;
/**
@@ -44,10 +46,12 @@
/** Stores the delegate used for implementing functionality related to the
* <code>FileConfiguration</code> interface.
*/
- private FileConfigurationDelegate delegate = createDelegate();
+ private FileConfigurationDelegate delegate;
protected AbstractHierarchicalFileConfiguration()
{
+ delegate = createDelegate();
+ initDelegate(delegate);
}
/**
@@ -58,6 +62,7 @@
*/
public AbstractHierarchicalFileConfiguration(String fileName) throws ConfigurationException
{
+ this();
// store the file name
delegate.setPath(fileName);
@@ -73,6 +78,7 @@
*/
public AbstractHierarchicalFileConfiguration(File file) throws ConfigurationException
{
+ this();
// set the file and update the url, the base path and the file name
setFile(file);
@@ -91,6 +97,7 @@
*/
public AbstractHierarchicalFileConfiguration(URL url) throws ConfigurationException
{
+ this();
// set the URL and update the base path and the file name
setURL(url);
@@ -244,7 +251,15 @@
public void reload()
{
- delegate.reload();
+ setDetailEvents(false);
+ try
+ {
+ delegate.reload();
+ }
+ finally
+ {
+ setDetailEvents(true);
+ }
}
public String getEncoding()
@@ -293,6 +308,32 @@
protected FileConfigurationDelegate createDelegate()
{
return new FileConfigurationDelegate();
+ }
+
+ /**
+ * Helper method for initializing the file configuration delegate.
+ *
+ * @param del the delegate
+ */
+ private void initDelegate(FileConfigurationDelegate del)
+ {
+ del.addConfigurationListener(new ConfigurationListener()
+ {
+ public void configurationChanged(ConfigurationEvent event)
+ {
+ // deliver reload events to registered listeners
+ setDetailEvents(true);
+ try
+ {
+ fireEvent(event.getType(), event.getPropertyName(), event
+ .getPropertyValue(), event.isBeforeUpdate());
+ }
+ finally
+ {
+ setDetailEvents(false);
+ }
+ }
+ });
}
/**
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/BaseConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/BaseConfiguration.java?rev=394529&r1=394528&r2=394529&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/BaseConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/BaseConfiguration.java Sun Apr 16 10:55:55 2006
@@ -1,5 +1,5 @@
/*
- * Copyright 2001-2005 The Apache Software Foundation.
+ * Copyright 2001-2006 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License")
* you may not use this file except in compliance with the License.
@@ -124,7 +124,7 @@
*
* @param key the key to remove along with corresponding value.
*/
- public void clearProperty(String key)
+ protected void clearPropertyDirect(String key)
{
if (containsKey(key))
{
@@ -137,7 +137,9 @@
*/
public void clear()
{
+ fireEvent(EVENT_CLEAR, null, null, true);
store.clear();
+ fireEvent(EVENT_CLEAR, null, null, false);
}
/**
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java?rev=394529&r1=394528&r2=394529&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java Sun Apr 16 10:55:55 2006
@@ -100,6 +100,12 @@
*/
public class HierarchicalConfiguration extends AbstractConfiguration implements Serializable, Cloneable
{
+ /** Constant for the clear tree event.*/
+ public static final int EVENT_CLEAR_TREE = 10;
+
+ /** Constant for the add nodes event.*/
+ public static final int EVENT_ADD_NODES = 11;
+
/** Stores the default expression engine to be used for new objects.*/
private static ExpressionEngine defaultExpressionEngine = new DefaultExpressionEngine();
@@ -315,6 +321,7 @@
return;
}
+ fireEvent(EVENT_ADD_NODES, key, nodes, true);
ConfigurationNode parent;
List target = fetchNodeList(key);
if (target.size() == 1)
@@ -346,6 +353,7 @@
parent.addChild(child);
}
}
+ fireEvent(EVENT_ADD_NODES, key, nodes, false);
}
/**
@@ -509,6 +517,8 @@
*/
public void setProperty(String key, Object value)
{
+ fireEvent(EVENT_SET_PROPERTY, key, value, true);
+
Iterator itNodes = fetchNodeList(key).iterator();
Iterator itValues;
if (!isDelimiterParsingDisabled())
@@ -535,6 +545,8 @@
{
clearNode((ConfigurationNode) itNodes.next());
}
+
+ fireEvent(EVENT_SET_PROPERTY, key, value, false);
}
/**
@@ -547,12 +559,14 @@
*/
public void clearTree(String key)
{
+ fireEvent(EVENT_CLEAR_TREE, key, null, true);
List nodes = fetchNodeList(key);
for (Iterator it = nodes.iterator(); it.hasNext();)
{
removeNode((ConfigurationNode) it.next());
}
+ fireEvent(EVENT_CLEAR_TREE, key, nodes, false);
}
/**
@@ -564,12 +578,15 @@
*/
public void clearProperty(String key)
{
+ fireEvent(EVENT_CLEAR_PROPERTY, key, null, true);
List nodes = fetchNodeList(key);
for (Iterator it = nodes.iterator(); it.hasNext();)
{
clearNode((ConfigurationNode) it.next());
}
+
+ fireEvent(EVENT_CLEAR_PROPERTY, key, null, false);
}
/**
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java?rev=394529&r1=394528&r2=394529&view=diff
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MapConfiguration.java Sun Apr 16 10:55:55 2006
@@ -103,7 +103,7 @@
return map.containsKey(key);
}
- public void clearProperty(String key)
+ protected void clearPropertyDirect(String key)
{
map.remove(key);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org