Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 4458 invoked from network); 10 Oct 2009 17:18:23 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 10 Oct 2009 17:18:23 -0000 Received: (qmail 78185 invoked by uid 500); 10 Oct 2009 17:18:22 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 78078 invoked by uid 500); 10 Oct 2009 17:18:22 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 78069 invoked by uid 99); 10 Oct 2009 17:18:22 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 10 Oct 2009 17:18:22 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 10 Oct 2009 17:18:08 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 52BB923888E3; Sat, 10 Oct 2009 17:17:46 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r823891 [1/2] - in /commons/proper/configuration/trunk: ./ conf/ src/java/org/apache/commons/configuration/ src/java/org/apache/commons/configuration/beanutils/ src/java/org/apache/commons/configuration/reloading/ src/java/org/apache/common... Date: Sat, 10 Oct 2009 17:17:45 -0000 To: commits@commons.apache.org From: rgoers@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20091010171746.52BB923888E3@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: rgoers Date: Sat Oct 10 17:17:44 2009 New Revision: 823891 URL: http://svn.apache.org/viewvc?rev=823891&view=rev Log: Fix CONFIGURATION-390 and CONFIGURATION-397 Added: commons/proper/configuration/trunk/conf/configA.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/configA.xml commons/proper/configuration/trunk/conf/configB.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/configB.xml commons/proper/configuration/trunk/conf/log4j-test.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/log4j-test.xml commons/proper/configuration/trunk/conf/testFileReloadConfigurationBuilder.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testFileReloadConfigurationBuilder.xml commons/proper/configuration/trunk/conf/testFileReloadConfigurationBuilder2.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testFileReloadConfigurationBuilder2.xml commons/proper/configuration/trunk/conf/testMultiConfiguration.xsd - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration.xsd commons/proper/configuration/trunk/conf/testMultiConfiguration_2001.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_2001.xml commons/proper/configuration/trunk/conf/testMultiConfiguration_2002.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_2002.xml commons/proper/configuration/trunk/conf/testMultiConfiguration_3001.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_3001.xml commons/proper/configuration/trunk/conf/testMultiConfiguration_3002.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiConfiguration_3002.xml commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder2.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiTenentConfigurationBuilder2.xml commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder3.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiTenentConfigurationBuilder3.xml commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder4.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testMultiTenentConfigurationBuilder4.xml commons/proper/configuration/trunk/conf/testVFSMultiTenentConfigurationBuilder1.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testVFSMultiTenentConfigurationBuilder1.xml commons/proper/configuration/trunk/conf/testVFSMultiTenentConfigurationBuilder2.xml - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/conf/testVFSMultiTenentConfigurationBuilder2.xml commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalReloadableConfiguration.java - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/HierarchicalReloadableConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/Lock.java - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/Lock.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/Reloadable.java - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/reloading/Reloadable.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileChangedReloadingStrategy.java - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration/reloading/VFSFileChangedReloadingStrategy.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/Logging.java - copied unchanged from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/Logging.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java - copied, changed from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/FileRandomReloadingStrategy.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java - copied, changed from r822131, commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration/reloading/TestVFSFileChangedReloadingStrategy.java Removed: commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder.xml commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder2.xml commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileMonitorReloadingStrategy.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestVFSFileMonitorReloadingStrategy.java Modified: commons/proper/configuration/trunk/ (props changed) commons/proper/configuration/trunk/conf/testConfigurationInterpolatorUpdate.xml (props changed) commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml commons/proper/configuration/trunk/conf/testSystemProperties.xml (props changed) commons/proper/configuration/trunk/pom.xml commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ (props changed) commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/ (props changed) commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestWebdavConfigurationBuilder.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestXMLConfiguration.java commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/reloading/TestFileChangedReloadingStrategy.java commons/proper/configuration/trunk/xdocs/ (props changed) commons/proper/configuration/trunk/xdocs/changes.xml commons/proper/configuration/trunk/xdocs/userguide/howto_filesystems.xml commons/proper/configuration/trunk/xdocs/userguide/howto_multitenant.xml Propchange: commons/proper/configuration/trunk/ ------------------------------------------------------------------------------ --- svn:mergeinfo (added) +++ svn:mergeinfo Sat Oct 10 17:17:44 2009 @@ -0,0 +1 @@ +/commons/proper/configuration/branches/CONFIGURATION_390:819412-822131 Propchange: commons/proper/configuration/trunk/conf/testConfigurationInterpolatorUpdate.xml ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Sat Oct 10 17:17:44 2009 @@ -0,0 +1,2 @@ +/commons/proper/configuration/branches/CONFIGURATION_390/conf/testConfigurationInterpolatorUpdate.xml:819412-822131 +/jakarta/commons/proper/configuration/trunk/conf/testConfigurationInterpolatorUpdate.xml:141756-560656,560658-560659 Modified: commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml (original) +++ commons/proper/configuration/trunk/conf/testMultiConfiguration_default.xml Sat Oct 10 17:17:44 2009 @@ -1,5 +1,6 @@ - + #40404040 #000000 Propchange: commons/proper/configuration/trunk/conf/testSystemProperties.xml ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Sat Oct 10 17:17:44 2009 @@ -0,0 +1,2 @@ +/commons/proper/configuration/branches/CONFIGURATION_390/conf/testSystemProperties.xml:819412-822131 +/jakarta/commons/proper/configuration/trunk/conf/testSystemProperties.xml:141756-560656,560658-560659 Modified: commons/proper/configuration/trunk/pom.xml URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/pom.xml?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/pom.xml (original) +++ commons/proper/configuration/trunk/pom.xml Sat Oct 10 17:17:44 2009 @@ -462,6 +462,7 @@ testdb.script *.properties *.dtd + *.xsd @@ -485,6 +486,8 @@ org.apache.maven.plugins maven-surefire-plugin + + once **/TestWebdavConfigurationBuilder.java @@ -494,6 +497,10 @@ java.awt.headless true + + org.apache.commons.logging.Log + org.apache.commons.configuration.Logging + @@ -579,6 +586,14 @@ + + + Propchange: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Sat Oct 10 17:17:44 2009 @@ -1 +1,2 @@ +/commons/proper/configuration/branches/CONFIGURATION_390/src/java/org/apache/commons/configuration:819412-822131 /commons/proper/configuration/branches/configuration2_experimental/src/main/java/org/apache/commons/configuration2:751544-751840,755692,757108 Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractFileConfiguration.java Sat Oct 10 17:17:44 2009 @@ -103,7 +103,7 @@ protected ReloadingStrategy strategy; /** A lock object for protecting reload operations.*/ - private Object reloadLock = new Object(); + protected Object reloadLock = new Lock("AbstractFileConfiguration"); /** Stores the encoding of the configuration file.*/ private String encoding; @@ -207,6 +207,11 @@ return this.fileSystem; } + public Object getReloadLock() + { + return reloadLock; + } + /** * Load the configuration from the underlying location. @@ -747,8 +752,11 @@ */ public void addProperty(String key, Object value) { - super.addProperty(key, value); - possiblySave(); + synchronized(reloadLock) + { + super.addProperty(key, value); + possiblySave(); + } } /** @@ -761,14 +769,20 @@ */ public void setProperty(String key, Object value) { - super.setProperty(key, value); - possiblySave(); + synchronized(reloadLock) + { + super.setProperty(key, value); + possiblySave(); + } } public void clearProperty(String key) { - super.clearProperty(key); - possiblySave(); + synchronized(reloadLock) + { + super.clearProperty(key); + possiblySave(); + } } public ReloadingStrategy getReloadingStrategy() @@ -795,6 +809,11 @@ */ public void reload() { + reload(false); + } + + public boolean reload(boolean checkReload) + { synchronized (reloadLock) { if (noReload == 0) @@ -833,6 +852,10 @@ { fireError(EVENT_RELOAD, null, null, e); // todo rollback the changes if the file can't be reloaded + if (checkReload) + { + return false; + } } finally { @@ -840,6 +863,7 @@ } } } + return true; } /** @@ -920,13 +944,19 @@ public boolean isEmpty() { reload(); - return super.isEmpty(); + synchronized(reloadLock) + { + return super.isEmpty(); + } } public boolean containsKey(String key) { reload(); - return super.containsKey(key); + synchronized(reloadLock) + { + return super.containsKey(key); + } } /** Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/AbstractHierarchicalFileConfiguration.java Sat Oct 10 17:17:44 2009 @@ -29,7 +29,10 @@ import org.apache.commons.configuration.event.ConfigurationEvent; import org.apache.commons.configuration.event.ConfigurationListener; +import org.apache.commons.configuration.event.ConfigurationErrorListener; +import org.apache.commons.configuration.event.ConfigurationErrorEvent; import org.apache.commons.configuration.reloading.ReloadingStrategy; +import org.apache.commons.configuration.reloading.Reloadable; /** *

Base class for implementing file based hierarchical configurations.

@@ -45,7 +48,8 @@ */ public abstract class AbstractHierarchicalFileConfiguration extends HierarchicalConfiguration -implements FileConfiguration, ConfigurationListener, FileSystemBased +implements FileConfiguration, ConfigurationListener, ConfigurationErrorListener, FileSystemBased, + Reloadable { /** Stores the delegate used for implementing functionality related to the * FileConfiguration interface. @@ -137,26 +141,38 @@ protected void addPropertyDirect(String key, Object obj) { - super.addPropertyDirect(key, obj); - delegate.possiblySave(); + synchronized(delegate.getReloadLock()) + { + super.addPropertyDirect(key, obj); + delegate.possiblySave(); + } } public void clearProperty(String key) { - super.clearProperty(key); - delegate.possiblySave(); + synchronized(delegate.getReloadLock()) + { + super.clearProperty(key); + delegate.possiblySave(); + } } public void clearTree(String key) { - super.clearTree(key); - delegate.possiblySave(); + synchronized(delegate.getReloadLock()) + { + super.clearTree(key); + delegate.possiblySave(); + } } public void setProperty(String key, Object value) { - super.setProperty(key, value); - delegate.possiblySave(); + synchronized(delegate.getReloadLock()) + { + super.setProperty(key, value); + delegate.possiblySave(); + } } public void load() throws ConfigurationException @@ -281,10 +297,15 @@ public void reload() { + reload(false); + } + + private boolean reload(boolean checkReload) + { setDetailEvents(false); try { - delegate.reload(); + return delegate.reload(checkReload); } finally { @@ -302,34 +323,58 @@ delegate.setEncoding(encoding); } + public Object getReloadLock() + { + return delegate.getReloadLock(); + } + public boolean containsKey(String key) { reload(); - return super.containsKey(key); + synchronized(delegate.getReloadLock()) + { + return super.containsKey(key); + } } public Iterator getKeys() { reload(); - return super.getKeys(); + synchronized(delegate.getReloadLock()) + { + return super.getKeys(); + } } public Iterator getKeys(String prefix) { reload(); - return super.getKeys(prefix); + synchronized(delegate.getReloadLock()) + { + return super.getKeys(prefix); + } } public Object getProperty(String key) { - reload(); - return super.getProperty(key); + if (reload(true)) + { + // Avoid reloading again and getting the same error. + synchronized(delegate.getReloadLock()) + { + return super.getProperty(key); + } + } + return null; } public boolean isEmpty() { reload(); - return super.isEmpty(); + synchronized(delegate.getReloadLock()) + { + return super.isEmpty(); + } } /** @@ -342,8 +387,11 @@ */ public void addNodes(String key, Collection nodes) { - super.addNodes(key, nodes); - delegate.possiblySave(); + synchronized(delegate.getReloadLock()) + { + super.addNodes(key, nodes); + delegate.possiblySave(); + } } /** @@ -356,7 +404,10 @@ protected List fetchNodeList(String key) { reload(); - return super.fetchNodeList(key); + synchronized(delegate.getReloadLock()) + { + return super.fetchNodeList(key); + } } /** @@ -394,6 +445,8 @@ private void initDelegate(FileConfigurationDelegate del) { del.addConfigurationListener(this); + del.addErrorListener(this); + del.setLogger(getLogger()); } /** @@ -418,6 +471,12 @@ } } + public void configurationError(ConfigurationErrorEvent event) + { + fireError(event.getType(), event.getPropertyName(), event.getPropertyValue(), + event.getCause()); + } + /** * Returns the file configuration delegate. * Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java Sat Oct 10 17:17:44 2009 @@ -169,7 +169,7 @@ * @since 1.3 * @version $Id$ */ -public class CombinedConfiguration extends HierarchicalConfiguration implements +public class CombinedConfiguration extends HierarchicalReloadableConfiguration implements ConfigurationListener, Cloneable { /** @@ -204,6 +204,12 @@ /** Stores a map with the named configurations. */ private Map namedConfigurations; + /** The default behavior is to ignore exceptions that occur during reload */ + private boolean ignoreReloadExceptions = true; + + /** Set to true when the backing file has changed */ + private boolean reloadRequired = false; + /** * An expression engine used for converting child configurations to * hierarchical ones. @@ -226,6 +232,18 @@ clear(); } + public CombinedConfiguration(NodeCombiner comb, Lock lock) + { + super(lock); + setNodeCombiner((comb != null) ? comb : DEFAULT_COMBINER); + clear(); + } + + public CombinedConfiguration(Lock lock) + { + this(null, lock); + } + /** * Creates a new instance of CombinedConfiguration that uses * a union combiner. @@ -234,7 +252,7 @@ */ public CombinedConfiguration() { - this(null); + this(null, null); } /** @@ -330,6 +348,26 @@ } /** + * Retrieves the value of the ignoreReloadExceptions flag. + * @return true if exceptions are ignored, false otherwise. + */ + public boolean isIgnoreReloadExceptions() + { + return ignoreReloadExceptions; + } + + /** + * If set to true then exceptions that occur during reloading will be + * ignored. If false then the exceptions will be allowed to be thrown + * back to the caller. + * @param ignoreReloadExceptions true if exceptions should be ignored. + */ + public void setIgnoreReloadExceptions(boolean ignoreReloadExceptions) + { + this.ignoreReloadExceptions = ignoreReloadExceptions; + } + + /** * Adds a new configuration to this combined configuration. It is possible * (but not mandatory) to give the new configuration a name. This name must * be unique, otherwise a ConfigurationRuntimeException will @@ -362,6 +400,10 @@ } ConfigData cd = new ConfigData(config, name, at); + if (getLogger().isDebugEnabled()) + { + getLogger().debug("Adding configuration " + config + " with name " + name); + } configurations.add(cd); if (name != null) { @@ -546,7 +588,7 @@ */ public void invalidate() { - combinedRoot = null; + reloadRequired = true; fireEvent(EVENT_COMBINED_INVALIDATE, null, null, false); } @@ -578,11 +620,15 @@ */ public ConfigurationNode getRootNode() { - if (combinedRoot == null) + synchronized(getReloadLock()) { - combinedRoot = constructCombinedNode(); + if (reloadRequired || combinedRoot == null) + { + combinedRoot = constructCombinedNode(); + reloadRequired = false; + } + return combinedRoot; } - return combinedRoot; } /** @@ -716,8 +762,10 @@ } catch (Exception ex) { - // ignore all exceptions, e.g. missing property exceptions - ; + if (!ignoreReloadExceptions) + { + throw new ConfigurationRuntimeException(ex); + } } } } @@ -731,6 +779,10 @@ { if (getNumberOfConfigurations() < 1) { + if (getLogger().isDebugEnabled()) + { + getLogger().debug("No configurations defined for " + this); + } return new ViewNode(); } @@ -763,23 +815,26 @@ */ private Configuration findSourceConfiguration(ConfigurationNode node) { - ConfigurationNode root = null; - ConfigurationNode current = node; - - // find the root node in this hierarchy - while (current != null) + synchronized(getReloadLock()) { - root = current; - current = current.getParentNode(); - } + ConfigurationNode root = null; + ConfigurationNode current = node; - // Check with the root nodes of the child configurations - for (Iterator it = configurations.iterator(); it.hasNext();) - { - ConfigData cd = (ConfigData) it.next(); - if (root == cd.getRootNode()) + // find the root node in this hierarchy + while (current != null) { - return cd.getConfiguration(); + root = current; + current = current.getParentNode(); + } + + // Check with the root nodes of the child configurations + for (Iterator it = configurations.iterator(); it.hasNext();) + { + ConfigData cd = (ConfigData) it.next(); + if (root == cd.getRootNode()) + { + return cd.getConfiguration(); + } } } @@ -889,11 +944,12 @@ } // Copy data of the root node to the new path - rootNode = ConfigurationUtils + ConfigurationNode root = ConfigurationUtils .convertToHierarchical(getConfiguration(), getConversionExpressionEngine()).getRootNode(); - atParent.appendChildren(rootNode); - atParent.appendAttributes(rootNode); + atParent.appendChildren(root); + atParent.appendAttributes(root); + rootNode = root; return result; } Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/ConfigurationUtils.java Sat Oct 10 17:17:44 2009 @@ -32,6 +32,7 @@ import org.apache.commons.configuration.event.ConfigurationErrorListener; import org.apache.commons.configuration.event.EventSource; import org.apache.commons.configuration.tree.ExpressionEngine; +import org.apache.commons.configuration.reloading.Reloadable; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.apache.commons.logging.Log; @@ -223,7 +224,19 @@ if (conf instanceof HierarchicalConfiguration) { - HierarchicalConfiguration hc = (HierarchicalConfiguration) conf; + HierarchicalConfiguration hc; + if (conf instanceof Reloadable) + { + Object lock = ((Reloadable) conf).getReloadLock(); + synchronized(lock) + { + hc = new HierarchicalConfiguration((HierarchicalConfiguration) conf); + } + } + else + { + hc = (HierarchicalConfiguration) conf; + } if (engine != null) { hc.setExpressionEngine(engine); Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java Sat Oct 10 17:17:44 2009 @@ -40,6 +40,7 @@ import org.apache.commons.configuration.resolver.EntityResolverSupport; import org.apache.commons.lang.text.StrLookup; import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.Log; import org.xml.sax.EntityResolver; /** @@ -651,6 +652,11 @@ .next(); ConfigurationDeclaration decl = new ConfigurationDeclaration(this, conf); + if (getLogger().isDebugEnabled()) + { + getLogger().debug("Creating configuration " + decl.getBeanClassName() + " with name " + + decl.getConfiguration().getString(ATTR_NAME)); + } AbstractConfiguration newConf = createConfigurationAt(decl); if (newConf != null) { @@ -1225,6 +1231,8 @@ */ static class ConfigurationBeanFactory implements BeanFactory { + private Log logger = LogFactory.getLog(DefaultConfigurationBuilder.class); + /** * Creates an instance of a bean class. This implementation expects that * the passed in bean declaration is a declaration for a configuration. @@ -1268,6 +1276,11 @@ } else { + if (logger.isDebugEnabled()) + { + logger.debug("Load failed for optional configuration " + tagName + ": " + + ex.getMessage()); + } // Notify registered error listeners decl.getConfigurationBuilder().fireError( EVENT_ERR_LOAD_OPTIONAL, Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultFileSystem.java Sat Oct 10 17:17:44 2009 @@ -16,6 +16,9 @@ */ package org.apache.commons.configuration; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import java.io.InputStream; import java.io.File; import java.io.IOException; @@ -35,6 +38,11 @@ */ public class DefaultFileSystem extends FileSystem { + /** + * The Log for diagnostic messages. + */ + private Log log = LogFactory.getLog(DefaultFileSystem.class); + public InputStream getInputStream(String basePath, String fileName) throws ConfigurationException { @@ -254,6 +262,10 @@ } catch (IOException e) { + if (log.isDebugEnabled()) + { + log.debug("Could not locate file " + fileName + " at " + basePath + ": " + e.getMessage()); + } return null; } } Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java Sat Oct 10 17:17:44 2009 @@ -32,8 +32,10 @@ import org.apache.commons.configuration.tree.ConfigurationNode; import org.apache.commons.configuration.tree.ExpressionEngine; import org.apache.commons.configuration.tree.NodeCombiner; +import org.apache.commons.configuration.interpol.ConfigurationInterpolator; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.lang.text.StrSubstitutor; /** * DynamicCombinedConfiguration allows a set of CombinedConfigurations to be used. Each CombinedConfiguration @@ -74,7 +76,9 @@ private NodeCombiner nodeCombiner; /** The name of the logger to use for each CombinedConfiguration */ - private String loggerName; + private String loggerName = DynamicCombinedConfiguration.class.getName(); + + private StrSubstitutor localSubst = new StrSubstitutor(new ConfigurationInterpolator()); /** * Creates a new instance of CombinedConfiguration and @@ -87,6 +91,8 @@ { super(); setNodeCombiner(comb); + setIgnoreReloadExceptions(false); + setLogger(LogFactory.getLog(DynamicCombinedConfiguration.class)); } /** @@ -98,6 +104,8 @@ public DynamicCombinedConfiguration() { super(); + setIgnoreReloadExceptions(false); + setLogger(LogFactory.getLog(DynamicCombinedConfiguration.class)); } public void setKeyPattern(String pattern) @@ -752,7 +760,7 @@ private CombinedConfiguration getCurrentConfig() { - String key = getSubstitutor().replace(keyPattern); + String key = localSubst.replace(keyPattern); CombinedConfiguration config; synchronized (getNodeCombiner()) { @@ -768,6 +776,7 @@ config.setLogger(log); } } + config.setIgnoreReloadExceptions(isIgnoreReloadExceptions()); config.setExpressionEngine(this.getExpressionEngine()); config.setDelimiterParsingDisabled(isDelimiterParsingDisabled()); config.setConversionExpressionEngine(getConversionExpressionEngine()); @@ -795,6 +804,10 @@ configs.put(key, config); } } + if (getLogger().isDebugEnabled()) + { + getLogger().debug("Returning config for " + key + ": " + config); + } return config; } Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/HierarchicalConfiguration.java Sat Oct 10 17:17:44 2009 @@ -194,6 +194,16 @@ } /** + * Object to synchronize on a reload. This class is not reloadable so this + * object isn't important + * @return + */ + public Object getReloadLock() + { + return this; + } + + /** * Returns the root node of this hierarchical configuration. This method * exists for backwards compatibility only. New code should use the * {@link #getRootNode()} method instead, which operates on Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java Sat Oct 10 17:17:44 2009 @@ -39,10 +39,13 @@ import org.apache.commons.configuration.tree.ExpressionEngine; import org.apache.commons.configuration.reloading.ReloadingStrategy; import org.apache.commons.configuration.resolver.EntityResolverSupport; +import org.apache.commons.configuration.interpol.ConfigurationInterpolator; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.apache.commons.lang.text.StrSubstitutor; import org.xml.sax.EntityResolver; +import org.xml.sax.SAXParseException; /** * This class provides access to multiple configuration files that reside in a location that @@ -92,7 +95,7 @@ private boolean attributeSplittingDisabled; /** The Logger name to use */ - private String loggerName = ""; + private String loggerName = MultiFileHierarchicalConfiguration.class.getName(); /** The Reloading strategy to use on created configurations */ private ReloadingStrategy fileStrategy; @@ -100,6 +103,8 @@ /** The EntityResolver */ private EntityResolver entityResolver; + private StrSubstitutor localSubst = new StrSubstitutor(new ConfigurationInterpolator()); + /** * Default Constructor. */ @@ -107,6 +112,7 @@ { super(); this.init = true; + setLogger(LogFactory.getLog(loggerName)); } /** @@ -118,6 +124,7 @@ super(); this.pattern = pathPattern; this.init = true; + setLogger(LogFactory.getLog(loggerName)); } public void setLoggerName(String name) @@ -402,6 +409,11 @@ return this.getConfiguration().subset(prefix); } + public Object getReloadLock() + { + return this.getConfiguration().getReloadLock(); + } + public Node getRoot() { return this.getConfiguration().getRoot(); @@ -621,6 +633,14 @@ listener.configurationError(event); } } + + if (event.getType() == AbstractFileConfiguration.EVENT_RELOAD) + { + if (isThrowable(event.getCause())) + { + throw new ConfigurationRuntimeException(event.getCause()); + } + } } /* @@ -669,7 +689,7 @@ { throw new ConfigurationRuntimeException("File pattern must be defined"); } - String path = getSubstitutor().replace(pattern); + String path = localSubst.replace(pattern); synchronized (configurationsMap) { if (configurationsMap.containsKey(path)) @@ -730,7 +750,7 @@ } catch (ConfigurationException ce) { - if (!ignoreException) + if (isThrowable(ce)) { throw new ConfigurationRuntimeException(ce); } @@ -746,6 +766,20 @@ return configuration; } + private boolean isThrowable(Throwable throwable) + { + if (!ignoreException) + { + return true; + } + Throwable cause = throwable.getCause(); + while (cause != null && !(cause instanceof SAXParseException)) + { + cause = cause.getCause(); + } + return cause != null; + } + /** * Clone the FileReloadingStrategy since each file needs its own. * @return A new FileReloadingStrategy. Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/PatternSubtreeConfigurationWrapper.java Sat Oct 10 17:17:44 2009 @@ -78,6 +78,11 @@ this.init = true; } + public Object getReloadLock() + { + return config.getReloadLock(); + } + public void addProperty(String key, Object value) { config.addProperty(makePath(key), value); Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/SubnodeConfiguration.java Sat Oct 10 17:17:44 2009 @@ -23,6 +23,7 @@ import org.apache.commons.configuration.interpol.ConfigurationInterpolator; import org.apache.commons.configuration.tree.ConfigurationNode; +import org.apache.commons.configuration.reloading.Reloadable; /** *

@@ -114,7 +115,7 @@ * @author Oliver Heger * @version $Id$ */ -public class SubnodeConfiguration extends HierarchicalConfiguration +public class SubnodeConfiguration extends HierarchicalReloadableConfiguration { /** * The serial version UID. @@ -136,6 +137,7 @@ */ public SubnodeConfiguration(HierarchicalConfiguration parent, ConfigurationNode root) { + super(parent instanceof Reloadable ? ((Reloadable) parent).getReloadLock() : null); if (parent == null) { throw new IllegalArgumentException( Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/XMLConfiguration.java Sat Oct 10 17:17:44 2009 @@ -49,6 +49,7 @@ import org.apache.commons.configuration.tree.ConfigurationNode; import org.apache.commons.configuration.resolver.EntityRegistry; import org.apache.commons.configuration.resolver.DefaultEntityResolver; +import org.apache.commons.logging.LogFactory; import org.w3c.dom.Attr; import org.w3c.dom.CDATASection; import org.w3c.dom.DOMException; @@ -226,6 +227,7 @@ public XMLConfiguration() { super(); + setLogger(LogFactory.getLog(XMLConfiguration.class)); } /** @@ -243,6 +245,7 @@ super(c); clearReferences(getRootNode()); setRootElementName(getRootNode().getName()); + setLogger(LogFactory.getLog(XMLConfiguration.class)); } /** @@ -255,6 +258,7 @@ public XMLConfiguration(String fileName) throws ConfigurationException { super(fileName); + setLogger(LogFactory.getLog(XMLConfiguration.class)); } /** @@ -267,6 +271,7 @@ public XMLConfiguration(File file) throws ConfigurationException { super(file); + setLogger(LogFactory.getLog(XMLConfiguration.class)); } /** @@ -279,6 +284,7 @@ public XMLConfiguration(URL url) throws ConfigurationException { super(url); + setLogger(LogFactory.getLog(XMLConfiguration.class)); } /** @@ -567,6 +573,7 @@ public void clear() { super.clear(); + setRoot(new Node()); document = null; } @@ -939,11 +946,11 @@ } catch (SAXParseException spe) { - this.getLogger().debug("Error parsing " + source.getSystemId(), spe); throw new ConfigurationException("Error parsing " + source.getSystemId(), spe); } catch (Exception e) { + this.getLogger().debug("Unable to load the configuraton", e); throw new ConfigurationException("Unable to load the configuration", e); } } Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/beanutils/BeanHelper.java Sat Oct 10 17:17:44 2009 @@ -263,7 +263,7 @@ if (!PropertyUtils.isWriteable(bean, propName)) { throw new ConfigurationRuntimeException("Property " + propName - + " cannot be set!"); + + " cannot be set on " + bean.getClass().getName()); } try Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/FileChangedReloadingStrategy.java Sat Oct 10 17:17:44 2009 @@ -23,6 +23,8 @@ import org.apache.commons.configuration.ConfigurationUtils; import org.apache.commons.configuration.FileConfiguration; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** *

A reloading strategy that will reload the configuration every time its @@ -64,6 +66,9 @@ /** A flag whether a reload is required.*/ private boolean reloading; + /** The Log to use for diagnostic messages */ + private Log logger = LogFactory.getLog(FileChangedReloadingStrategy.class); + public void setConfiguration(FileConfiguration configuration) { this.configuration = configuration; @@ -85,6 +90,10 @@ lastChecked = now; if (hasChanged()) { + if (logger.isDebugEnabled()) + { + logger.debug("File change detected: " + getName()); + } reloading = true; } } @@ -141,6 +150,11 @@ File file = getFile(); if (file == null || !file.exists()) { + if (logger.isWarnEnabled() && lastModified != 0) + { + logger.warn("File was deleted: " + getName(file)); + lastModified = 0; + } return false; } @@ -186,4 +200,27 @@ return ConfigurationUtils.fileFromURL(url); } } + + private String getName() + { + return getName(getFile()); + } + + private String getName(File file) + { + String name = configuration.getURL().toString(); + if (name == null) + { + if (file != null) + { + name = file.getAbsolutePath(); + } + else + { + name = "base: " + configuration.getBasePath() + + "file: " + configuration.getFileName(); + } + } + return name; + } } Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java (original) +++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/resolver/CatalogResolver.java Sat Oct 10 17:17:44 2009 @@ -23,6 +23,7 @@ import org.apache.xml.resolver.Catalog; import org.apache.xml.resolver.readers.CatalogReader; import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.impl.NoOpLog; import org.apache.commons.configuration.FileSystem; import org.apache.commons.configuration.ConfigurationException; @@ -199,7 +200,7 @@ } catch (Exception e) { - log.debug("Failed to create InputSource for " + resolved + " (" + log.warn("Failed to create InputSource for " + resolved + " (" + e.toString() + ")"); return null; } @@ -229,7 +230,7 @@ */ public void setLogger(Log log) { - this.log = (log != null) ? log : new NoOpLog(); + this.log = (log != null) ? log : LogFactory.getLog(CatalogResolver.class); } private synchronized org.apache.xml.resolver.tools.CatalogResolver getResolver() Propchange: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Sat Oct 10 17:17:44 2009 @@ -1 +1,2 @@ +/commons/proper/configuration/branches/CONFIGURATION_390/src/test/org/apache/commons/configuration:819412-822131 /commons/proper/configuration/branches/configuration2_experimental/src/test/java/org/apache/commons/configuration2:751544-751840,755692,757108 Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java (original) +++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestCombinedConfiguration.java Sat Oct 10 17:17:44 2009 @@ -34,10 +34,13 @@ import org.apache.commons.configuration.event.ConfigurationEvent; import org.apache.commons.configuration.event.ConfigurationListener; import org.apache.commons.configuration.reloading.FileAlwaysReloadingStrategy; +import org.apache.commons.configuration.reloading.FileRandomReloadingStrategy; import org.apache.commons.configuration.tree.DefaultExpressionEngine; import org.apache.commons.configuration.tree.NodeCombiner; import org.apache.commons.configuration.tree.OverrideCombiner; import org.apache.commons.configuration.tree.UnionCombiner; +import org.apache.commons.configuration.tree.MergeCombiner; +import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine; /** * Test class for CombinedConfiguration. @@ -764,6 +767,75 @@ .getInt("xmlReload1")); } + public void testConcurrentGetAndReload() throws Exception + { + final int threadCount = 5; + final int loopCount = 1000; + config.setForceReloadCheck(true); + config.setNodeCombiner(new MergeCombiner()); + final XMLConfiguration xml = new XMLConfiguration("configA.xml"); + xml.setReloadingStrategy(new FileRandomReloadingStrategy()); + config.addConfiguration(xml); + final XMLConfiguration xml2 = new XMLConfiguration("configB.xml"); + xml2.setReloadingStrategy(new FileRandomReloadingStrategy()); + config.addConfiguration(xml2); + config.setExpressionEngine(new XPathExpressionEngine()); + + assertEquals(config.getString("/property[@name='config']/@value"), "100"); + + Thread testThreads[] = new Thread[threadCount]; + int failures[] = new int[threadCount]; + + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i] = new ReloadThread(config, failures, i, loopCount); + testThreads[i].start(); + } + + int totalFailures = 0; + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i].join(); + totalFailures += failures[i]; + } + assertTrue(totalFailures + " failures Occurred", totalFailures == 0); + } + + private class ReloadThread extends Thread + { + CombinedConfiguration combined; + int[] failures; + int index; + int count; + + ReloadThread(CombinedConfiguration config, int[] failures, int index, int count) + { + combined = config; + this.failures = failures; + this.index = index; + this.count = count; + } + public void run() + { + failures[index] = 0; + for (int i = 0; i < count; i++) + { + try + { + String value = combined.getString("/property[@name='config']/@value"); + if (value == null || !value.equals("100")) + { + ++failures[index]; + } + } + catch (Exception ex) + { + ++failures[index]; + } + } + } + } + /** * Helper method for writing a file. The file is also added to a list and * will be deleted in teadDown() automatically. Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java (original) +++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDynamicCombinedConfiguration.java Sat Oct 10 17:17:44 2009 @@ -21,12 +21,15 @@ import junit.framework.TestCase; import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine; +import org.apache.commons.lang.text.StrLookup; public class TestDynamicCombinedConfiguration extends TestCase { private static String PATTERN ="${sys:Id}"; private static String PATTERN1 = "target/test-classes/testMultiConfiguration_${sys:Id}.xml"; private static String DEFAULT_FILE = "target/test-classes/testMultiConfiguration_default.xml"; + private static final File MULTI_TENENT_FILE = new File( + "conf/testMultiTenentConfigurationBuilder4.xml"); public void testConfiguration() throws Exception { @@ -57,9 +60,186 @@ assertEquals("a\\,b\\,c", config.getString("split/list2")); } + public void testConcurrentGetAndReload() throws Exception + { + final int threadCount = 5; + final int loopCount = 500; + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_TENENT_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + + assertEquals(config.getString("rowsPerPage"), "50"); + Thread testThreads[] = new Thread[threadCount]; + int failures[] = new int[threadCount]; + + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i] = new ReloadThread(config, failures, i, loopCount, false, null, "50"); + testThreads[i].start(); + } + + int totalFailures = 0; + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i].join(); + totalFailures += failures[i]; + } + assertTrue(totalFailures + " failures Occurred", totalFailures == 0); + } + + public void testConcurrentGetAndReload2() throws Exception + { + final int threadCount = 5; + final int loopCount = 500; + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_TENENT_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + + assertEquals(config.getString("rowsPerPage"), "50"); + + Thread testThreads[] = new Thread[threadCount]; + int failures[] = new int[threadCount]; + System.setProperty("Id", "2002"); + assertEquals(config.getString("rowsPerPage"), "25"); + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i] = new ReloadThread(config, failures, i, loopCount, false, null, "25"); + testThreads[i].start(); + } + + int totalFailures = 0; + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i].join(); + totalFailures += failures[i]; + } + System.getProperties().remove("Id"); + assertTrue(totalFailures + " failures Occurred", totalFailures == 0); + } + + public void testConcurrentGetAndReloadMultipleClients() throws Exception + { + final int threadCount = 5; + final int loopCount = 500; + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_TENENT_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + + assertEquals(config.getString("rowsPerPage"), "50"); + + Thread testThreads[] = new Thread[threadCount]; + int failures[] = new int[threadCount]; + String[] ids = new String[] {null, "2002", "3001", "3002", "3003"}; + String[] expected = new String[] {"50", "25", "15", "25", "50"}; + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i] = new ReloadThread(config, failures, i, loopCount, true, ids[i], expected[i]); + testThreads[i].start(); + } + + int totalFailures = 0; + for (int i = 0; i < testThreads.length; ++i) + { + testThreads[i].join(); + totalFailures += failures[i]; + } + System.getProperties().remove("Id"); + if (totalFailures != 0) + { + System.out.println("Failures:"); + for (int i = 0; i < testThreads.length; ++i) + { + System.out.println("Thread " + i + " " + failures[i]); + } + } + assertTrue(totalFailures + " failures Occurred", totalFailures == 0); + } + + private class ReloadThread extends Thread + { + CombinedConfiguration combined; + int[] failures; + int index; + int count; + String expected; + String id; + boolean useId; + + ReloadThread(CombinedConfiguration config, int[] failures, int index, int count, + boolean useId, String id, String expected) + { + combined = config; + this.failures = failures; + this.index = index; + this.count = count; + this.expected = expected; + this.id = id; + this.useId = useId; + } + public void run() + { + failures[index] = 0; + + if (useId) + { + ThreadLookup.setId(id); + } + for (int i = 0; i < count; i++) + { + try + { + String value = combined.getString("rowsPerPage", null); + if (value == null || !value.equals(expected)) + { + ++failures[index]; + } + } + catch (Exception ex) + { + ++failures[index]; + } + } + } + } + private void verify(String key, DynamicCombinedConfiguration config, int rows) { System.setProperty("Id", key); assertTrue(config.getInt("rowsPerPage") == rows); } + + public static class ThreadLookup extends StrLookup + { + private static ThreadLocal id = new ThreadLocal(); + + + + public ThreadLookup() + { + + } + + public static void setId(String value) + { + id.set(value); + } + + public String lookup(String key) + { + if (key == null || !key.equals("Id")) + { + return null; + } + String value = System.getProperty("Id"); + if (value != null) + { + return value; + } + return (String)id.get(); + + } + } } Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java (original) +++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestMultiFileHierarchicalConfiguration.java Sat Oct 10 17:17:44 2009 @@ -19,6 +19,9 @@ import junit.framework.TestCase; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; +import org.xml.sax.SAXParseException; + +import java.io.*; /** * Unit test for simple MultiConfigurationTest. @@ -27,6 +30,15 @@ { private static String PATTERN1 = "target/test-classes/testMultiConfiguration_${sys:Id}.xml"; + private static final File MULTI_TENENT_FILE = new File( + "conf/testMultiTenentConfigurationBuilder2.xml"); + + private static final File MULTI_TENENT_FILE2 = new File( + "target/test-classes/testMultiTenentConfigurationBuilder2.xml"); + + private static final File MULTI_RELOAD_FILE = new File( + "conf/testMultiTenentConfigurationBuilder3.xml"); + /** * Rigourous Test :-) */ @@ -48,4 +60,238 @@ System.setProperty("Id", "1003"); assertTrue(config.getInt("rowsPerPage") == 35); } + + public void testSchemaValidationError() throws Exception + { + System.clearProperty("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_TENENT_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + try + { + System.setProperty("Id", "2001"); + config.getInt("rowsPerPage"); + fail("No exception thrown"); + } + catch (Exception ex) + { + Throwable cause = ex.getCause(); + while (cause != null && !(cause instanceof SAXParseException)) + { + cause = cause.getCause(); + } + assertTrue("SAXParseException was not thrown", cause instanceof SAXParseException); + } + } + + public void testSchemaValidation() throws Exception + { + System.clearProperty("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_TENENT_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + System.setProperty("Id", "2002"); + int rows = config.getInt("rowsPerPage"); + assertTrue("expected: " + rows + " actual: " + "25", 25 == rows); + } + + public void testMissingFile() throws Exception + { + System.clearProperty("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_TENENT_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + System.setProperty("Id", "3099"); + int rows = config.getInt("rowsPerPage"); + assertTrue("expected: " + rows + " actual: " + "50", 50 == rows); + + } + + public void testFileReload1() throws Exception + { + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_RELOAD_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + + // create a new configuration + File input = new File("target/test-classes/testMultiConfiguration_3001.xml"); + File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml"); + output.delete(); + output.getParentFile().mkdir(); + copyFile(input, output); + + assertNotNull(config); + verify("3001", config, 15); + Thread.sleep(1100); + XMLConfiguration x = new XMLConfiguration(); + x.setFile(output); + x.setAttributeSplittingDisabled(true); + x.setDelimiterParsingDisabled(true); + x.load(); + x.setProperty("rowsPerPage", "35"); + //Insure orginal timestamp and new timestamp aren't the same second. + Thread.sleep(1100); + x.save(); + verify("3001", config, 35); + output.delete(); + } + + public void testFileReload2() throws Exception + { + // create a new configuration + File input = new File("target/test-classes/testMultiConfiguration_3002.xml"); + File output = new File("target/test-classes/testwrite/testMultiConfiguration_3002.xml"); + output.delete(); + + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_RELOAD_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + assertNotNull(config); + // The file should not exist yet. + verify("3002", config, 50); + + output.getParentFile().mkdir(); + copyFile(input, output); + Thread.sleep(600); + verify("3002", config, 25); + output.delete(); + } + + public void testFileReload3() throws Exception + { + // create a new configuration + File input = new File("target/test-classes/testMultiConfiguration_3001.xml"); + File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml"); + output.delete(); + output.getParentFile().mkdir(); + + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_RELOAD_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + assertNotNull(config); + //The file does not exist yet. + verify("3001", config, 50); + copyFile(input, output); + //Sleep so refreshDelay elapses + Thread.sleep(600); + verify("3001", config, 15); + Thread.sleep(500); + XMLConfiguration x = new XMLConfiguration(); + x.setFile(output); + x.setAttributeSplittingDisabled(true); + x.setDelimiterParsingDisabled(true); + x.load(); + x.setProperty("rowsPerPage", "35"); + // Insure original timestamp and new timestamp are not the same second. + Thread.sleep(1100); + x.save(); + verify("3001", config, 35); + output.delete(); + } + + + public void testReloadDefault() throws Exception + { + // create a new configuration + String defaultName = "target/test-classes/testMultiConfiguration_default.xml"; + File input = new File(defaultName); + + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_TENENT_FILE2); + CombinedConfiguration config = factory.getConfiguration(true); + assertNotNull(config); + verify("3001", config, 15); + verify("3002", config, 25); + System.setProperty("Id", "3002"); + config.addProperty("/ TestProp", "Test"); + assertTrue("Property not added", "Test".equals(config.getString("TestProp"))); + System.getProperties().remove("Id"); + //Sleep so refreshDelay elapses + Thread.sleep(600); + long time = System.currentTimeMillis(); + long original = input.lastModified(); + input.setLastModified(time); + File defaultFile = new File(defaultName); + long newTime = defaultFile.lastModified(); + assertTrue("time mismatch", original != newTime); + Thread.sleep(600); + verify("3001", config, 15); + verify("3002", config, 25); + System.setProperty("Id", "3002"); + String test = config.getString("TestProp"); + assertNull("Property was not cleared by reload", test); + } + + + public void testFileReloadSchemaValidationError() throws Exception + { + System.getProperties().remove("Id"); + DefaultConfigurationBuilder factory = new DefaultConfigurationBuilder(); + factory.setFile(MULTI_RELOAD_FILE); + CombinedConfiguration config = factory.getConfiguration(true); + + // create a new configuration + File input = new File("target/test-classes/testMultiConfiguration_3001.xml"); + File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml"); + output.delete(); + output.getParentFile().mkdir(); + copyFile(input, output); + + assertNotNull(config); + verify("3001", config, 15); + Thread.sleep(1100); + XMLConfiguration x = new XMLConfiguration(); + x.setFile(output); + x.setAttributeSplittingDisabled(true); + x.setDelimiterParsingDisabled(true); + x.load(); + x.setProperty("rowsPerPage", "test"); + //Insure orginal timestamp and new timestamp aren't the same second. + Thread.sleep(1100); + x.save(); + System.setProperty("Id", "3001"); + try + { + config.getInt("rowsPerPage"); + fail("No exception was thrown"); + } + catch (Exception ex) + { + + } + + output.delete(); + } + + private void copyFile(File input, File output) throws IOException + { + Reader reader = new FileReader(input); + Writer writer = new FileWriter(output); + char[] buffer = new char[4096]; + int n = 0; + while (-1 != (n = reader.read(buffer))) + { + writer.write(buffer, 0, n); + } + reader.close(); + writer.close(); + } + + private void verify(String key, CombinedConfiguration config, int rows) + { + if (key == null) + { + System.getProperties().remove("Id"); + } + else + { + System.setProperty("Id", key); + } + int actual = config.getInt("rowsPerPage"); + assertTrue("expected: " + rows + " actual: " + actual, actual == rows); + } } Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java?rev=823891&r1=823890&r2=823891&view=diff ============================================================================== --- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java (original) +++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java Sat Oct 10 17:17:44 2009 @@ -31,11 +31,8 @@ import org.apache.commons.configuration.beanutils.BeanHelper; import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; -import org.apache.commons.configuration.reloading.VFSFileMonitorReloadingStrategy; import org.apache.commons.configuration.tree.DefaultConfigurationNode; import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine; -import org.apache.commons.configuration.event.ConfigurationListener; -import org.apache.commons.configuration.event.ConfigurationEvent; /** * Test class for DefaultConfigurationBuilder. @@ -43,7 +40,7 @@ * @author Oliver Heger * @version $Id$ */ -public class TestVFSConfigurationBuilder extends TestCase implements ConfigurationListener +public class TestVFSConfigurationBuilder extends TestCase { /** Test configuration definition file. */ private static final File TEST_FILE = new File( @@ -91,30 +88,21 @@ private static final File FILESYSTEM_FILE = new File( "conf/testFileSystem.xml"); - private static final File FILEMONITOR_FILE = new File( - "target/test-classes/testFileMonitorConfigurationBuilder.xml"); + private static final File FILERELOAD_FILE = new File( + "target/test-classes/testFileReloadConfigurationBuilder.xml"); - private static final File FILEMONITOR2_FILE = new File( - "target/test-classes/testFileMonitorConfigurationBuilder2.xml"); + private static final File MULTI_RELOAD_FILE1 = new File( + "target/test-classes/testVFSMultiTenentConfigurationBuilder1.xml"); - private static final String FILEMONITOR_URI = "file://" + System.getProperty("user.dir") - + "/target/test-classes/testFileMonitorConfigurationBuilder2.xml"; + private static final File MULTI_RELOAD_FILE2 = new File( + "target/test-classes/testVFSMultiTenentConfigurationBuilder2.xml"); /** Constant for the name of an optional configuration.*/ private static final String OPTIONAL_NAME = "optionalConfig"; - /** true when a file is changed */ - private boolean configChanged = false; - /** Stores the object to be tested. */ DefaultConfigurationBuilder factory; - public TestVFSConfigurationBuilder() - { - super(); - VFSFileMonitorReloadingStrategy.stopMonitor(); - } - protected void setUp() throws Exception { super.setUp(); @@ -1005,7 +993,7 @@ } } - public void testFileMonitor1() throws Exception + public void testFileReload1() throws Exception { // create a new configuration File input = new File("target/test-classes/testMultiConfiguration_1001.xml"); @@ -1013,116 +1001,147 @@ output.delete(); output.getParentFile().mkdir(); copyFile(input, output); + // Sleep to make sure the file timestamp is not in the same second as "now". + Thread.sleep(1100); - factory.setFile(FILEMONITOR_FILE); + factory.setFile(FILERELOAD_FILE); FileSystem.resetDefaultFileSystem(); System.getProperties().remove("Id"); CombinedConfiguration config = factory.getConfiguration(true); assertNotNull(config); - config.addConfigurationListener(this); verify("1001", config, 15); - - // Allow time for FileMonitor to set up. - Thread.sleep(1000); XMLConfiguration x = new XMLConfiguration(output); x.setProperty("rowsPerPage", "50"); x.save(); - - waitForChange(); verify("1001", config, 50); output.delete(); - VFSFileMonitorReloadingStrategy.stopMonitor(); } - public void testFileMonitor2() throws Exception + public void testFileReload2() throws Exception { // create a new configuration File input = new File("target/test-classes/testMultiConfiguration_1002.xml"); File output = new File("target/test-classes/testwrite/testMultiConfiguration_1002.xml"); output.delete(); - factory.setFile(FILEMONITOR_FILE); + factory.setFile(FILERELOAD_FILE); FileSystem.resetDefaultFileSystem(); System.getProperties().remove("Id"); CombinedConfiguration config = factory.getConfiguration(true); - config.addConfigurationListener(this); assertNotNull(config); verify("1002", config, 50); - Thread.sleep(1000); - + // Sleep to make sure the file timestamp is not in the same second as "now". + Thread.sleep(1100); output.getParentFile().mkdir(); copyFile(input, output); - - // Allow time for the monitor to notice the change. - //Thread.sleep(2000); - waitForChange(); verify("1002", config, 25); output.delete(); - VFSFileMonitorReloadingStrategy.stopMonitor(); } - - public void testFileMonitor3() throws Exception + public void testFileReload3() throws Exception { // create a new configuration File input = new File("target/test-classes/testMultiConfiguration_1001.xml"); File output = new File("target/test-classes/testwrite/testMultiConfiguration_1001.xml"); output.delete(); output.getParentFile().mkdir(); - copyFile(input, output); - factory.setFile(FILEMONITOR2_FILE); + factory.setFile(FILERELOAD_FILE); + FileSystem.resetDefaultFileSystem(); System.getProperties().remove("Id"); CombinedConfiguration config = factory.getConfiguration(true); assertNotNull(config); - config.addConfigurationListener(this); + verify("1001", config, 50); + copyFile(input, output); + // Sleep to make sure the file timestamp is not in the same second as "now". + Thread.sleep(1100); verify("1001", config, 15); - - // Allow time for FileMonitor to set up. - Thread.sleep(1000); XMLConfiguration x = new XMLConfiguration(output); - x.setProperty("rowsPerPage", "50"); + x.setProperty("rowsPerPage", "25"); x.save(); - // Let FileMonitor detect the change. - //Thread.sleep(2000); - waitForChange(); - verify("1001", config, 50); + // Sleep to make sure the file timestamp is not in the same second as "now". + Thread.sleep(1100); + verify("1001", config, 25); output.delete(); - VFSFileMonitorReloadingStrategy.stopMonitor(); } - public void testFileMonitor4() throws Exception + public void testReloadDefault() throws Exception { // create a new configuration - File input = new File("target/test-classes/testMultiConfiguration_1002.xml"); - File output = new File("target/test-classes/testwrite/testMultiConfiguration_1002.xml"); - output.delete(); + String defaultName = "target/test-classes/testMultiConfiguration_default.xml"; + File input = new File(defaultName); - factory.setFileName(FILEMONITOR_URI); System.getProperties().remove("Id"); - + factory.setFile(MULTI_RELOAD_FILE1); CombinedConfiguration config = factory.getConfiguration(true); assertNotNull(config); - config.addConfigurationListener(this); + verify("3001", config, 15); + verify("3002", config, 25); + System.setProperty("Id", "3002"); + config.addProperty("/ TestProp", "Test"); + assertTrue("Property not added", "Test".equals(config.getString("TestProp"))); + System.getProperties().remove("Id"); + //Sleep so refreshDelay elapses + Thread.sleep(600); + long time = System.currentTimeMillis(); + long original = input.lastModified(); + input.setLastModified(time); + File defaultFile = new File(defaultName); + long newTime = defaultFile.lastModified(); + assertTrue("time mismatch", original != newTime); + Thread.sleep(600); + verify("3001", config, 15); + verify("3002", config, 25); + System.setProperty("Id", "3002"); + String test = config.getString("TestProp"); + assertNull("Property was not cleared by reload", test); + } - verify("1002", config, 50); - Thread.sleep(1000); + public void testFileReloadSchemaValidationError() throws Exception + { + System.getProperties().remove("Id"); + factory.setFile(MULTI_RELOAD_FILE2); + CombinedConfiguration config = factory.getConfiguration(true); + + // create a new configuration + File input = new File("target/test-classes/testMultiConfiguration_3001.xml"); + File output = new File("target/test-classes/testwrite/testMultiConfiguration_3001.xml"); + output.delete(); output.getParentFile().mkdir(); copyFile(input, output); - // Allow time for the monitor to notice the change. - //Thread.sleep(2000); - waitForChange(); - verify("1002", config, 25); + assertNotNull(config); + verify("3001", config, 15); + Thread.sleep(1100); + XMLConfiguration x = new XMLConfiguration(); + x.setFile(output); + x.setAttributeSplittingDisabled(true); + x.setDelimiterParsingDisabled(true); + x.load(); + x.setProperty("rowsPerPage", "test"); + //Insure orginal timestamp and new timestamp aren't the same second. + Thread.sleep(1100); + x.save(); + System.setProperty("Id", "3001"); + try + { + config.getInt("rowsPerPage"); + fail("No exception was thrown"); + } + catch (Exception ex) + { + + } + output.delete(); - VFSFileMonitorReloadingStrategy.stopMonitor(); } + private void copyFile(File input, File output) throws IOException { Reader reader = new FileReader(input); @@ -1151,39 +1170,4 @@ int actual = config.getInt("rowsPerPage"); assertTrue("expected: " + rows + " actual: " + actual, actual == rows); } - - private void waitForChange() - { - synchronized(this) - { - try - { - int count = 0; - while (!configChanged && count++ <= 3) - { - this.wait(5000); - } - } - catch (InterruptedException ie) - { - throw new IllegalStateException("wait timed out"); - } - finally - { - configChanged = false; - } - } - } - - public void configurationChanged(ConfigurationEvent event) - { - if (event.getType() == AbstractFileConfiguration.EVENT_CONFIG_CHANGED) - { - synchronized(this) - { - configChanged = true; - this.notify(); - } - } - } } \ No newline at end of file