You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by rg...@apache.org on 2009/04/11 08:23:15 UTC
svn commit: r764168 - in /commons/proper/configuration/trunk: ./ conf/
conf/01/ src/java/org/apache/commons/configuration/
src/java/org/apache/commons/configuration/beanutils/
src/java/org/apache/commons/configuration/interpol/
src/java/org/apache/comm...
Author: rgoers
Date: Sat Apr 11 06:23:13 2009
New Revision: 764168
URL: http://svn.apache.org/viewvc?rev=764168&view=rev
Log:
CONFIGURATION-380 - Add expression evaluation during interpolation. Fix various bugs in VFS reloading and in multi file handling
Added:
commons/proper/configuration/trunk/conf/01/
commons/proper/configuration/trunk/conf/01/testMultiConfiguration_1001.xml
- copied unchanged from r760159, commons/proper/configuration/trunk/conf/testMultiConfiguration_1001.xml
commons/proper/configuration/trunk/conf/testExpression.xml
- copied, changed from r760159, commons/proper/configuration/trunk/conf/testExtendedClass.xml
commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder.xml
- copied, changed from r760159, commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ExprLookup.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/TreeUtils.java
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestExprLookup.java
Modified:
commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml
commons/proper/configuration/trunk/pom.xml
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/CombinedConfiguration.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DefaultConfigurationBuilder.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/DynamicCombinedConfiguration.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/MultiFileHierarchicalConfiguration.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/VFSFileSystem.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/VFSFileMonitorReloadingStrategy.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/MergeCombiner.java
commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/NodeCombiner.java
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java
commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestVFSConfigurationBuilder.java
commons/proper/configuration/trunk/xdocs/changes.xml
commons/proper/configuration/trunk/xdocs/userguide/howto_basicfeatures.xml
Copied: commons/proper/configuration/trunk/conf/testExpression.xml (from r760159, commons/proper/configuration/trunk/conf/testExtendedClass.xml)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testExpression.xml?p2=commons/proper/configuration/trunk/conf/testExpression.xml&p1=commons/proper/configuration/trunk/conf/testExtendedClass.xml&r1=760159&r2=764168&rev=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/conf/testExtendedClass.xml (original)
+++ commons/proper/configuration/trunk/conf/testExpression.xml Sat Apr 11 06:23:13 2009
@@ -2,33 +2,37 @@
<!-- Test configuration definition file that demonstrates complex initialization -->
<configuration>
<header>
- <result delimiterParsingDisabled="true"
- config-class="org.apache.commons.configuration.TestDefaultConfigurationBuilder$ExtendedCombinedConfiguration">
- <nodeCombiner config-class="org.apache.commons.configuration.tree.OverrideCombiner"/>
- <expressionEngine config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
+ <result delimiterParsingDisabled="true" forceReloadCheck="true"
+ config-class="org.apache.commons.configuration.DynamicCombinedConfiguration"
+ keyPattern="$${sys:Id}">
+ <nodeCombiner config-class="org.apache.commons.configuration.tree.MergeCombiner"/>
+ <expressionEngine
+ config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
</result>
- <combiner>
- <override>
- <list-nodes>
- <node>table</node>
- <node>list</node>
- </list-nodes>
- </override>
- </combiner>
+ <lookups>
+ <lookup config-prefix="expr"
+ config-class="org.apache.commons.configuration.interpol.ExprLookup">
+ <variables>
+ <variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
+ </variables>
+ </lookup>
+ </lookups>
+ <providers>
+ <provider config-tag="multifile"
+ config-class="org.apache.commons.configuration.DefaultConfigurationBuilder$FileConfigurationProvider"
+ configurationClass="org.apache.commons.configuration.MultiFileHierarchicalConfiguration"/>
+ </providers>
</header>
- <system/>
- <properties fileName="test.properties" throwExceptionOnMissing="true"
- config-name="properties">
- <reloadingStrategy config-class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy"
- refreshDelay="10000"/>
- </properties>
- <!-- Fetch the file name from a variable -->
- <xml fileName="${test_file_xml}" config-name="xml">
- <expressionEngine config-class="org.apache.commons.configuration.tree.DefaultExpressionEngine"
- propertyDelimiter="/" indexStart="[" indexEnd="]"/>
- </xml>
- <additional>
- <xml config-name="combiner1" fileName="${test_file_combine}"/> -->
- <xml config-name="combiner2" fileName="testcombine2.xml"/>
- </additional>
+ <override>
+ <multifile filePattern='$$${expr:String.right("$[sys:Id]", 2)}/testMultiConfiguration_$$${sys:Id}.xml'
+ config-name="clientConfig" delimiterParsingDisabled="true">
+ <expressionEngine
+ config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
+ </multifile>
+ <xml fileName="testMultiConfiguration_default.xml"
+ config-name="defaultConfig" delimiterParsingDisabled="true">
+ <expressionEngine
+ config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
+ </xml>
+ </override>
</configuration>
\ No newline at end of file
Copied: commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder.xml (from r760159, commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml)
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder.xml?p2=commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder.xml&p1=commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml&r1=760159&r2=764168&rev=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml (original)
+++ commons/proper/configuration/trunk/conf/testFileMonitorConfigurationBuilder.xml Sat Apr 11 06:23:13 2009
@@ -9,6 +9,7 @@
<expressionEngine
config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
</result>
+ <fileSystem config-class="org.apache.commons.configuration.VFSFileSystem"/>
<providers>
<provider config-tag="multifile"
config-class="org.apache.commons.configuration.DefaultConfigurationBuilder$FileConfigurationProvider"
@@ -16,15 +17,19 @@
</providers>
</header>
<override>
- <multifile filePattern="testMultiConfiguration_$$${sys:Id}.xml"
- config-name="clientConfig" delimiterParsingDisabled="true">
+ <multifile filePattern="testwrite/testMultiConfiguration_$$${sys:Id}.xml"
+ config-name="clientConfig" delimiterParsingDisabled="true" schemaValidation="false">
<expressionEngine
config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
+ <reloadingStrategy delay="500"
+ config-class="org.apache.commons.configuration.reloading.VFSFileMonitorReloadingStrategy"/>
</multifile>
<xml fileName="testMultiConfiguration_default.xml"
config-name="defaultConfig" delimiterParsingDisabled="true">
<expressionEngine
config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
+ <reloadingStrategy
+ config-class="org.apache.commons.configuration.reloading.VFSFileMonitorReloadingStrategy"/>
</xml>
</override>
</configuration>
\ No newline at end of file
Modified: commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml (original)
+++ commons/proper/configuration/trunk/conf/testMultiTenentConfigurationBuilder.xml Sat Apr 11 06:23:13 2009
@@ -2,7 +2,7 @@
<!-- Test configuration definition file that demonstrates complex initialization -->
<configuration>
<header>
- <result delimiterParsingDisabled="true" forceReloadCheck="true"
+ <result delimiterParsingDisabled="true" forceReloadCheck="true" loggerName="TestLogger"
config-class="org.apache.commons.configuration.DynamicCombinedConfiguration"
keyPattern="$${sys:Id}">
<nodeCombiner config-class="org.apache.commons.configuration.tree.MergeCombiner"/>
@@ -17,7 +17,7 @@
</header>
<override>
<multifile filePattern="testMultiConfiguration_$$${sys:Id}.xml"
- config-name="clientConfig" delimiterParsingDisabled="true">
+ config-name="clientConfig" delimiterParsingDisabled="true" schemaValidation="false">
<expressionEngine
config-class="org.apache.commons.configuration.tree.xpath.XPathExpressionEngine"/>
</multifile>
Modified: commons/proper/configuration/trunk/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/pom.xml?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/pom.xml (original)
+++ commons/proper/configuration/trunk/pom.xml Sat Apr 11 06:23:13 2009
@@ -250,6 +250,13 @@
</dependency>
<dependency>
+ <groupId>commons-jexl</groupId>
+ <artifactId>commons-jexl</artifactId>
+ <version>1.1</version>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-vfs</artifactId>
<version>2.0-SNAPSHOT</version>
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=764168&r1=764167&r2=764168&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 Apr 11 06:23:13 2009
@@ -23,6 +23,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.io.PrintStream;
+import java.io.ByteArrayOutputStream;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.event.ConfigurationListener;
@@ -34,6 +36,7 @@
import org.apache.commons.configuration.tree.NodeCombiner;
import org.apache.commons.configuration.tree.UnionCombiner;
import org.apache.commons.configuration.tree.ViewNode;
+import org.apache.commons.configuration.tree.TreeUtils;
/**
* <p>
@@ -737,6 +740,13 @@
node = getNodeCombiner().combine(node,
((ConfigData) it.next()).getTransformedRoot());
}
+ if (getLogger().isDebugEnabled())
+ {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ PrintStream stream = new PrintStream(os);
+ TreeUtils.printTree(stream, node);
+ getLogger().debug(os.toString());
+ }
return node;
}
}
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=764168&r1=764167&r2=764168&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 Apr 11 06:23:13 2009
@@ -703,7 +703,9 @@
HierarchicalConfiguration config = (HierarchicalConfiguration) it.next();
XMLBeanDeclaration decl = new XMLBeanDeclaration(config);
String key = config.getString(KEY_LOOKUP_KEY);
- ConfigurationInterpolator.registerGlobalLookup(key, (StrLookup) BeanHelper.createBean(decl));
+ StrLookup lookup = (StrLookup) BeanHelper.createBean(decl);
+ BeanHelper.setProperty(lookup, "configuration", this);
+ ConfigurationInterpolator.registerGlobalLookup(key, lookup);
}
}
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=764168&r1=764167&r2=764168&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 Apr 11 06:23:13 2009
@@ -32,6 +32,8 @@
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.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* DynamicCombinedConfiguration allows a set of CombinedConfigurations to be used. Each CombinedConfiguration
@@ -71,6 +73,9 @@
/** Stores the combiner. */
private NodeCombiner nodeCombiner;
+ /** The name of the logger to use for each CombinedConfiguration */
+ private String loggerName;
+
/**
* Creates a new instance of <code>CombinedConfiguration</code> and
* initializes the combiner to be used.
@@ -106,6 +111,15 @@
}
/**
+ * Set the name of the Logger to use on each CombinedConfiguration.
+ * @param name The Logger name.
+ */
+ public void setLoggerName(String name)
+ {
+ this.loggerName = name;
+ }
+
+ /**
* Returns the node combiner that is used for creating the combined node
* structure.
*
@@ -746,9 +760,16 @@
if (config == null)
{
config = new CombinedConfiguration(getNodeCombiner());
+ if (loggerName != null)
+ {
+ Log log = LogFactory.getLog(loggerName);
+ if (log != null)
+ {
+ config.setLogger(log);
+ }
+ }
config.setExpressionEngine(this.getExpressionEngine());
config.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
- config.setDetailEvents(this.isDetailEvents());
config.setConversionExpressionEngine(getConversionExpressionEngine());
config.setListDelimiter(getListDelimiter());
Iterator iter = config.getErrorListeners().iterator();
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=764168&r1=764167&r2=764168&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 Apr 11 06:23:13 2009
@@ -37,6 +37,10 @@
import org.apache.commons.configuration.event.ConfigurationListener;
import org.apache.commons.configuration.tree.ConfigurationNode;
import org.apache.commons.configuration.tree.ExpressionEngine;
+import org.apache.commons.configuration.reloading.ReloadingStrategy;
+import org.apache.commons.beanutils.BeanUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* This class provides access to multiple configuration files that reside in a location that
@@ -76,6 +80,18 @@
/** Return an empty configuration if loading fails */
private boolean ignoreException = true;
+ /** Capture the schema validation setting */
+ private boolean schemaValidation;
+
+ /** Stores a flag whether DTD or Schema validation should be performed.*/
+ private boolean validating;
+
+ /** A flag whether attribute splitting is disabled.*/
+ private boolean attributeSplittingDisabled;
+
+ /** The Logger name to use */
+ private String loggerName = "";
+
/**
* Default Constructor.
*/
@@ -96,6 +112,11 @@
this.init = true;
}
+ public void setLoggerName(String name)
+ {
+ this.loggerName = name;
+ }
+
/**
* Set the File pattern
* @param pathPattern The pattern for the path to the configuration.
@@ -105,6 +126,36 @@
this.pattern = pathPattern;
}
+ public boolean isSchemaValidation()
+ {
+ return schemaValidation;
+ }
+
+ public void setSchemaValidation(boolean schemaValidation)
+ {
+ this.schemaValidation = schemaValidation;
+ }
+
+ public boolean isValidating()
+ {
+ return validating;
+ }
+
+ public void setValidating(boolean validating)
+ {
+ this.validating = validating;
+ }
+
+ public boolean isAttributeSplittingDisabled()
+ {
+ return attributeSplittingDisabled;
+ }
+
+ public void setAttributeSplittingDisabled(boolean attributeSplittingDisabled)
+ {
+ this.attributeSplittingDisabled = attributeSplittingDisabled;
+ }
+
/**
* Set to true if an empty Configuration should be returned when loading fails. If
* false an exception will be thrown.
@@ -620,11 +671,23 @@
XMLConfiguration configuration = new XMLConfiguration();
try
{
+ if (loggerName != null)
+ {
+ Log log = LogFactory.getLog(loggerName);
+ if (log != null)
+ {
+ configuration.setLogger(log);
+ }
+ }
+ configuration.setBasePath(getBasePath());
configuration.setFileName(path);
+ configuration.setFileSystem(getFileSystem());
configuration.setExpressionEngine(getExpressionEngine());
- configuration.setReloadingStrategy(getReloadingStrategy());
+ configuration.setReloadingStrategy(createReloadingStrategy());
configuration.setDelimiterParsingDisabled(isDelimiterParsingDisabled());
- configuration.setDetailEvents(this.isDetailEvents());
+ configuration.setValidating(validating);
+ configuration.setSchemaValidation(schemaValidation);
+ configuration.setAttributeSplittingDisabled(attributeSplittingDisabled);
configuration.setListDelimiter(getListDelimiter());
configuration.addConfigurationListener(this);
configuration.addErrorListener(this);
@@ -647,4 +710,27 @@
return configuration;
}
+
+ /**
+ * Clone the FileReloadingStrategy since each file needs its own.
+ * @return A new FileReloadingStrategy.
+ */
+ private ReloadingStrategy createReloadingStrategy()
+ {
+ if (getReloadingStrategy() == null)
+ {
+ return null;
+ }
+ try
+ {
+ ReloadingStrategy strategy = (ReloadingStrategy) BeanUtils.cloneBean(getReloadingStrategy());
+ strategy.setConfiguration(null);
+ return strategy;
+ }
+ catch (Exception ex)
+ {
+ return null;
+ }
+
+ }
}
Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/VFSFileSystem.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/VFSFileSystem.java?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/VFSFileSystem.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/VFSFileSystem.java Sat Apr 11 06:23:13 2009
@@ -24,6 +24,8 @@
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileType;
import org.apache.commons.vfs.FileSystemOptions;
+import org.apache.commons.vfs.UserAuthenticator;
+import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.UriParser;
import org.apache.commons.vfs.provider.http.HttpFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.webdav.WebdavFileSystemConfigBuilder;
@@ -336,10 +338,14 @@
{
return setWebdavOptions(opts, map);
}
- if (scheme.equals("http"))
+ else if (scheme.equals("http"))
{
return setHttpOptions(opts, map);
}
+ else
+ {
+ return setDefaultOptions(opts, map);
+ }
}
return opts;
}
@@ -365,6 +371,8 @@
private FileSystemOptions setHttpOptions(FileSystemOptions opts, Map map)
{
+ setDefaultOptions(opts, map);
+
if (httpBuilder == null || map == null)
{
return opts;
@@ -390,4 +398,28 @@
}
return opts;
}
+
+ private FileSystemOptions setDefaultOptions(FileSystemOptions opts, Map map)
+ {
+ DefaultFileSystemConfigBuilder builder = DefaultFileSystemConfigBuilder.getInstance();
+
+ if (builder == null || map == null)
+ {
+ return opts;
+ }
+
+ if (map.containsKey("userAuthenticator"))
+ {
+ UserAuthenticator auth = (UserAuthenticator) map.get("userAuthenticator");
+ try
+ {
+ builder.setUserAuthenticator(opts, auth);
+ }
+ catch (FileSystemException e)
+ {
+ return opts;
+ }
+ }
+ return opts;
+ }
}
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=764168&r1=764167&r2=764168&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 Apr 11 06:23:13 2009
@@ -22,6 +22,7 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.beans.PropertyDescriptor;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
@@ -158,6 +159,32 @@
public static void initBean(Object bean, BeanDeclaration data)
throws ConfigurationRuntimeException
{
+ initBeanProperties(bean, data);
+
+ Map nestedBeans = data.getNestedBeanDeclarations();
+ if (nestedBeans != null)
+ {
+ for (Iterator it = nestedBeans.entrySet().iterator(); it.hasNext();)
+ {
+ Map.Entry e = (Map.Entry) it.next();
+ String propName = (String) e.getKey();
+ Class defaultClass = getDefaultClass(bean, propName);
+ initProperty(bean, propName, createBean(
+ (BeanDeclaration) e.getValue(), defaultClass));
+ }
+ }
+ }
+
+ /**
+ * Initializes the beans properties.
+ *
+ * @param bean the bean to be initialized
+ * @param data the bean declaration
+ * @throws ConfigurationRuntimeException if a property cannot be set
+ */
+ public static void initBeanProperties(Object bean, BeanDeclaration data)
+ throws ConfigurationRuntimeException
+ {
Map properties = data.getBeanProperties();
if (properties != null)
{
@@ -168,17 +195,28 @@
initProperty(bean, propName, e.getValue());
}
}
+ }
- Map nestedBeans = data.getNestedBeanDeclarations();
- if (nestedBeans != null)
+ /**
+ * Return the Class of the property if it can be determined.
+ * @param bean The bean containing the property.
+ * @param propName The name of the property.
+ * @return The class associated with the property or null.
+ */
+ private static Class getDefaultClass(Object bean, String propName)
+ {
+ try
{
- for (Iterator it = nestedBeans.entrySet().iterator(); it.hasNext();)
+ PropertyDescriptor desc = PropertyUtils.getPropertyDescriptor(bean, propName);
+ if (desc == null)
{
- Map.Entry e = (Map.Entry) it.next();
- String propName = (String) e.getKey();
- initProperty(bean, propName, createBean(
- (BeanDeclaration) e.getValue(), null));
+ return null;
}
+ return desc.getPropertyType();
+ }
+ catch (Exception ex)
+ {
+ return null;
}
}
@@ -215,6 +253,33 @@
}
/**
+ * Set a property on the bean only if the property exists
+ * @param bean the bean
+ * @param propName the name of the property
+ * @param value the property's value
+ * @throws ConfigurationRuntimeException if the property is not writeable or
+ * an error occurred
+ */
+ public static void setProperty(Object bean, String propName, Object value)
+ {
+ if (PropertyUtils.isWriteable(bean, propName))
+ {
+ try
+ {
+ BeanUtils.setProperty(bean, propName, value);
+ }
+ catch (IllegalAccessException iaex)
+ {
+ throw new ConfigurationRuntimeException(iaex);
+ }
+ catch (InvocationTargetException itex)
+ {
+ throw new ConfigurationRuntimeException(itex);
+ }
+ }
+ }
+
+ /**
* The main method for creating and initializing beans from a configuration.
* This method will return an initialized instance of the bean class
* specified in the passed in bean declaration. If this declaration does not
Added: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ExprLookup.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ExprLookup.java?rev=764168&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ExprLookup.java (added)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ExprLookup.java Sat Apr 11 06:23:13 2009
@@ -0,0 +1,290 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.interpol;
+
+import org.apache.commons.lang.text.StrLookup;
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.configuration.AbstractConfiguration;
+import org.apache.commons.configuration.ConfigurationRuntimeException;
+import org.apache.commons.jexl.JexlHelper;
+import org.apache.commons.jexl.JexlContext;
+import org.apache.commons.jexl.Expression;
+import org.apache.commons.jexl.ExpressionFactory;
+
+import java.util.Iterator;
+import java.util.ArrayList;
+
+/**
+ * Lookup that allows expressions to be evaluated.
+ *
+ * <pre>
+ * ExprLookup.Variables vars = new ExprLookup.Variables();
+ * vars.add(new ExprLookup.Variable("String", org.apache.commons.lang.StringUtils.class));
+ * vars.add(new ExprLookup.Variable("Util", new Utility("Hello")));
+ * vars.add(new ExprLookup.Variable("System", "Class:java.lang.System"));
+ * XMLConfiguration config = new XMLConfiguration(TEST_FILE);
+ * config.setLogger(log);
+ * ExprLookup lookup = new ExprLookup(vars);
+ * lookup.setConfiguration(config);
+ * String str = lookup.lookup("'$[element] ' + String.trimToEmpty('$[space.description]')");
+ * </pre>
+ *
+ * In the example above TEST_FILE contains xml that looks like:
+ * <pre>
+ * <configuration>
+ * <element>value</element>
+ * <space xml:space="preserve">
+ * <description xml:space="default"> Some text </description>
+ * </space>
+ * </configuration>
+ * </pre>
+ *
+ * The result will be "value Some text".
+ *
+ * This lookup uses Apache Commons Jexl and requires that the dependency be added to any
+ * projects which use this.
+ *
+ * @since 1.7
+ * @author <a
+ * href="http://commons.apache.org/configuration/team-list.html">Commons Configuration team</a>
+ * @version $Id: $
+ */
+public class ExprLookup extends StrLookup
+{
+ /** Prefix to identify a Java Class object */
+ private static final String CLASS = "Class:";
+
+ /** The default prefix for subordinate lookup expressions */
+ private static final String DEFAULT_PREFIX = "$[";
+
+ /** The default suffix for subordinate lookup expressions */
+ private static final String DEFAULT_SUFFIX = "]";
+
+ /** Configuration being operated on */
+ private AbstractConfiguration configuration;
+
+ /** The JexlContext */
+ private JexlContext context = JexlHelper.createContext();
+
+ /** The String to use to start subordinate lookup expressions */
+ private String prefixMatcher = DEFAULT_PREFIX;
+
+ /** The String to use to terminate subordinate lookup expressions */
+ private String suffixMatcher = DEFAULT_SUFFIX;
+
+ /**
+ * The default constructor. Will get used when the Lookup is constructed via
+ * configuration.
+ */
+ public ExprLookup()
+ {
+ }
+
+ /**
+ * Constructor for use by applications.
+ * @param list The list of objects to be accessible in expressions.
+ */
+ public ExprLookup(Variables list)
+ {
+ setVariables(list);
+ }
+
+ /**
+ * Constructor for use by applications.
+ * @param list The list of objects to be accessible in expressions.
+ * @param prefix The prefix to use for subordinate lookups.
+ * @param suffix The suffix to use for subordinate lookups.
+ */
+ public ExprLookup(Variables list, String prefix, String suffix)
+ {
+ this(list);
+ setVariablePrefixMatcher(prefix);
+ setVariableSuffixMatcher(suffix);
+ }
+
+ /**
+ * Set the prefix to use to identify subordinate expressions. This cannot be the
+ * same as the prefix used for the primary expression.
+ * @param prefix The String identifying the beginning of the expression.
+ */
+ public void setVariablePrefixMatcher(String prefix)
+ {
+ prefixMatcher = prefix;
+ }
+
+
+ /**
+ * Set the suffix to use to identify subordinate expressions. This cannot be the
+ * same as the suffix used for the primary expression.
+ * @param suffix The String identifying the end of the expression.
+ */
+ public void setVariableSuffixMatcher(String suffix)
+ {
+ suffixMatcher = suffix;
+ }
+
+ /**
+ * Add the Variables that will be accessible within expressions.
+ * @param list The list of Variables.
+ */
+ public void setVariables(Variables list)
+ {
+ Iterator iter = list.iterator();
+ while (iter.hasNext())
+ {
+ Variable var = (Variable) iter.next();
+ context.getVars().put(var.getName(), var.getValue());
+ }
+ }
+
+ /**
+ * Returns the list of Variables that are accessible within expressions.
+ * @return the List of Variables that are accessible within expressions.
+ */
+ public Variables getVariables()
+ {
+ return null;
+ }
+
+ /**
+ * Set the configuration to be used to interpolate subordinate expressiosn.
+ * @param config The Configuration.
+ */
+ public void setConfiguration(AbstractConfiguration config)
+ {
+ this.configuration = config;
+ }
+
+ /**
+ * Evaluates the expression.
+ * @param var The expression.
+ * @return The String result of the expression.
+ */
+ public String lookup(String var)
+ {
+ ConfigurationInterpolator interp = configuration.getInterpolator();
+ StrSubstitutor subst = new StrSubstitutor(interp, prefixMatcher, suffixMatcher,
+ StrSubstitutor.DEFAULT_ESCAPE);
+
+ String result = subst.replace(var);
+
+ try
+ {
+ Expression exp = ExpressionFactory.createExpression(result);
+ result = (String) exp.evaluate(context);
+ }
+ catch (Exception e)
+ {
+ configuration.getLogger().debug("Error encountered evaluation " + result, e);
+ }
+
+ return result;
+ }
+
+ /**
+ * List wrapper used to allow the Variables list to be created as beans in
+ * DefaultConfigurationBuilder.
+ */
+ public static class Variables extends ArrayList
+ {
+ public void setVariable(Variable var)
+ {
+ add(var);
+ }
+
+ public Variable getVariable()
+ {
+ if (size() > 0)
+ {
+ return (Variable) get(size() - 1);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ }
+
+ /**
+ * The key and corresponding object that will be made available to the
+ * JexlContext for use in expressions.
+ */
+ public static class Variable
+ {
+ /** The name to be used in expressions */
+ private String key;
+
+ /** The object to be accessed in expressions */
+ private Object value;
+
+ public Variable()
+ {
+ }
+
+ public Variable(String name, Object value)
+ {
+ setName(name);
+ setValue(value);
+ }
+
+ public String getName()
+ {
+ return key;
+ }
+
+ public void setName(String name)
+ {
+ this.key = name;
+ }
+
+ public Object getValue()
+ {
+ return value;
+ }
+
+ public void setValue(Object value) throws ConfigurationRuntimeException
+ {
+ try
+ {
+ if (!(value instanceof String))
+ {
+ this.value = value;
+ return;
+ }
+ String val = (String) value;
+ String name = StringUtils.removeStartIgnoreCase(val, CLASS);
+ Class clazz = ClassUtils.getClass(name);
+ if (name.length() == val.length())
+ {
+ this.value = clazz.newInstance();
+ }
+ else
+ {
+ this.value = clazz;
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationRuntimeException("Unable to create " + value, e);
+ }
+
+ }
+ }
+}
Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileMonitorReloadingStrategy.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileMonitorReloadingStrategy.java?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileMonitorReloadingStrategy.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/reloading/VFSFileMonitorReloadingStrategy.java Sat Apr 11 06:23:13 2009
@@ -90,7 +90,7 @@
*/
public void setConfiguration(FileConfiguration configuration)
{
- if (configuration instanceof FileSystemBased)
+ if (configuration == null || configuration instanceof FileSystemBased)
{
this.configuration = configuration;
}
@@ -105,6 +105,10 @@
*/
public void init()
{
+ if (configuration.getURL() == null && configuration.getFileName() == null)
+ {
+ return;
+ }
if (this.configuration == null)
{
throw new IllegalStateException("No configuration has been set for this strategy");
@@ -134,6 +138,10 @@
FileSystem fs = ((FileSystemBased) configuration).getFileSystem();
String uri = fs.getPath(null, configuration.getURL(), configuration.getBasePath(),
configuration.getFileName());
+ if (uri == null)
+ {
+ throw new ConfigurationRuntimeException("Unable to determine file to monitor");
+ }
FileObject file = fsManager.resolveFile(uri);
file.getFileSystem().addListener(file, this);
fm.addFile(file);
Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/MergeCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/MergeCombiner.java?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/MergeCombiner.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/MergeCombiner.java Sat Apr 11 06:23:13 2009
@@ -54,13 +54,6 @@
public ConfigurationNode combine(ConfigurationNode node1, ConfigurationNode node2)
{
- ConfigurationNode result = doCombine(node1, node2);
- printTree(result);
- return result;
- }
-
- public ConfigurationNode doCombine(ConfigurationNode node1, ConfigurationNode node2)
- {
ViewNode result = createViewNode();
result.setName(node1.getName());
result.setValue(node1.getValue());
@@ -74,7 +67,7 @@
ConfigurationNode child2 = canCombine(node1, node2, child1, children2);
if (child2 != null)
{
- result.addChild(doCombine(child1, child2));
+ result.addChild(combine(child1, child2));
children2.remove(child2);
}
else
Modified: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/NodeCombiner.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/NodeCombiner.java?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/NodeCombiner.java (original)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/NodeCombiner.java Sat Apr 11 06:23:13 2009
@@ -19,8 +19,6 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
-import java.util.Iterator;
-import java.io.PrintStream;
/**
* <p>
@@ -57,9 +55,6 @@
/** Stores a list with node names that are known to be list nodes. */
protected Set listNodes;
- /** Stream to write debug output to */
- private PrintStream debugStream;
-
/**
* Creates a new instance of <code>NodeCombiner</code>.
*/
@@ -126,54 +121,4 @@
{
return new ViewNode();
}
-
- /**
- * Set the output stream to write the tree to.
- * @param stream The OutputStream.
- */
- public void setDebugStream(PrintStream stream)
- {
- this.debugStream = stream;
- }
-
- protected void printTree(ConfigurationNode result)
- {
- if (debugStream != null)
- {
- printTree("", result);
- }
- }
-
- private void printTree(String indent, ConfigurationNode result)
- {
- StringBuffer buffer = new StringBuffer(indent).append("<").append(result.getName());
- Iterator iter = result.getAttributes().iterator();
- while (iter.hasNext())
- {
- ConfigurationNode node = (ConfigurationNode) iter.next();
- buffer.append(" ").append(node.getName()).append("='").append(node.getValue()).append("'");
- }
- buffer.append(">");
- debugStream.print(buffer.toString());
- if (result.getValue() != null)
- {
- debugStream.print(result.getValue());
- }
- boolean newline = false;
- if (result.getChildrenCount() > 0)
- {
- debugStream.print("\n");
- iter = result.getChildren().iterator();
- while (iter.hasNext())
- {
- printTree(indent + " ", (ConfigurationNode) iter.next());
- }
- newline = true;
- }
- if (newline)
- {
- debugStream.print(indent);
- }
- debugStream.println("</" + result.getName() + ">");
- }
}
Added: commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/TreeUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/TreeUtils.java?rev=764168&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/TreeUtils.java (added)
+++ commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/tree/TreeUtils.java Sat Apr 11 06:23:13 2009
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.tree;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+
+/**
+ * Utility methods.
+ * @author <a
+ * href="http://commons.apache.org/configuration/team-list.html">Commons
+ * Configuration team</a>
+ * @version $Id: NodeCombiner.java 761171 2009-04-02 05:42:41Z rgoers $
+ * @since 1.6
+ */
+public final class TreeUtils
+{
+ /** Prevent creating this class. */
+ private TreeUtils()
+ {
+ }
+
+ /**
+ * Print out the data in the configuration.
+ * @param stream The OutputStream.
+ * @param result The root node of the tree.
+ */
+ public static void printTree(PrintStream stream, ConfigurationNode result)
+ {
+ if (stream != null)
+ {
+ printTree(stream, "", result);
+ }
+ }
+
+ private static void printTree(PrintStream stream, String indent, ConfigurationNode result)
+ {
+ StringBuffer buffer = new StringBuffer(indent).append("<").append(result.getName());
+ Iterator iter = result.getAttributes().iterator();
+ while (iter.hasNext())
+ {
+ ConfigurationNode node = (ConfigurationNode) iter.next();
+ buffer.append(" ").append(node.getName()).append("='").append(node.getValue()).append("'");
+ }
+ buffer.append(">");
+ stream.print(buffer.toString());
+ if (result.getValue() != null)
+ {
+ stream.print(result.getValue());
+ }
+ boolean newline = false;
+ if (result.getChildrenCount() > 0)
+ {
+ stream.print("\n");
+ iter = result.getChildren().iterator();
+ while (iter.hasNext())
+ {
+ printTree(stream, indent + " ", (ConfigurationNode) iter.next());
+ }
+ newline = true;
+ }
+ if (newline)
+ {
+ stream.print(indent);
+ }
+ stream.println("</" + result.getName() + ">");
+ }
+}
Modified: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java (original)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/TestDefaultConfigurationBuilder.java Sat Apr 11 06:23:13 2009
@@ -18,6 +18,7 @@
import java.io.File;
import java.io.IOException;
+import java.io.StringWriter;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
@@ -33,6 +34,13 @@
import org.apache.commons.configuration.tree.ConfigurationNode;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.apache.commons.lang.text.StrLookup;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.impl.Log4JLogger;
+import org.apache.log4j.WriterAppender;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+import org.apache.log4j.SimpleLayout;
/**
* Test class for DefaultConfigurationBuilder.
@@ -82,6 +90,9 @@
private static final File MULTI_TENENT_FILE = new File(
"conf/testMultiTenentConfigurationBuilder.xml");
+ private static final File EXPRESSION_FILE = new File(
+ "conf/testExpression.xml");
+
/** Constant for the name of an optional configuration.*/
private static final String OPTIONAL_NAME = "optionalConfig";
@@ -873,12 +884,25 @@
public void testMultiTenentConfiguration3() throws Exception
{
factory.setFile(MULTI_TENENT_FILE);
+ StringWriter writer = new StringWriter();
+ WriterAppender app = new WriterAppender(new SimpleLayout(), writer);
+ Log log = LogFactory.getLog("TestLogger");
+ Logger logger = ((Log4JLogger)log).getLogger();
+ logger.addAppender(app);
+ logger.setLevel(Level.DEBUG);
+ logger.setAdditivity(false);
+
System.setProperty("Id", "1005");
CombinedConfiguration config = factory.getConfiguration(true);
assertTrue("Incorrect configuration", config instanceof DynamicCombinedConfiguration);
verify("1001", config, 15);
+ String xml = writer.getBuffer().toString();
+ assertNotNull("No XML returned", xml);
+ assertTrue("Incorect configuration data", xml.contains("<rowsPerPage>15</rowsPerPage>"));
+ logger.removeAppender(app);
+ logger.setLevel(Level.OFF);
verify("1002", config, 25);
verify("1003", config, 35);
verify("1004", config, 50);
@@ -902,19 +926,26 @@
{
factory.setFile(MULTI_TENENT_FILE);
System.setProperty("Id", "1004");
+ Map map = new HashMap();
+ map.put("default", "${colors.header4}");
+ map.put("background", "#40404040");
+ map.put("text", "#000000");
+ map.put("header", "#444444");
CombinedConfiguration config = factory.getConfiguration(true);
assertTrue("Incorrect configuration", config instanceof DynamicCombinedConfiguration);
List list = config.configurationsAt("colors/*");
Iterator iter = list.iterator();
- System.out.println("Color nodes");
while (iter.hasNext())
{
SubnodeConfiguration sub = (SubnodeConfiguration)iter.next();
ConfigurationNode node = sub.getRootNode();
String value = (node.getValue() == null) ? "null" : node.getValue().toString();
- System.out.println(node.getName() + "=" + value);
+ if (map.containsKey(node.getName()))
+ {
+ assertEquals(map.get(node.getName()), value);
+ }
}
}
@@ -935,6 +966,18 @@
assertEquals("a\\,b\\,c", config.getString("split/list2"));
}
+ public void testExpression() throws Exception
+ {
+ factory.setFile(EXPRESSION_FILE);
+ factory.setAttributeSplittingDisabled(true);
+ System.getProperties().remove("Id");
+
+ CombinedConfiguration config = factory.getConfiguration(true);
+ assertTrue("Incorrect configuration", config instanceof DynamicCombinedConfiguration);
+
+ verify("1001", config, 15);
+ }
+
private void verify(String key, CombinedConfiguration config, int rows)
{
System.setProperty("Id", key);
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=764168&r1=764167&r2=764168&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 Apr 11 06:23:13 2009
@@ -18,6 +18,10 @@
import java.io.File;
import java.io.IOException;
+import java.io.Reader;
+import java.io.FileReader;
+import java.io.Writer;
+import java.io.FileWriter;
import java.util.Collection;
import java.util.Set;
import java.util.List;
@@ -81,6 +85,9 @@
private static final File FILESYSTEM_FILE = new File(
"conf/testFileSystem.xml");
+ private static final File FILEMONITOR_FILE = new File(
+ "target/test-classes/testFileMonitorConfigurationBuilder.xml");
+
/** Constant for the name of an optional configuration.*/
private static final String OPTIONAL_NAME = "optionalConfig";
@@ -966,6 +973,48 @@
}
}
+ public void testFileMonitor() 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.getParentFile().mkdir();
+ copyFile(input, output);
+
+ factory.setFile(FILEMONITOR_FILE);
+ FileSystem.resetDefaultFileSystem();
+ System.getProperties().remove("Id");
+
+ CombinedConfiguration config = factory.getConfiguration(true);
+ assertNotNull(config);
+ 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();
+ // Let FileMonitor detect the change.
+ Thread.sleep(2000);
+ verify("1001", config, 50);
+ }
+
+ 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)
{
System.setProperty("Id", key);
Added: commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestExprLookup.java
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestExprLookup.java?rev=764168&view=auto
==============================================================================
--- commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestExprLookup.java (added)
+++ commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestExprLookup.java Sat Apr 11 06:23:13 2009
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.configuration.interpol;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.StringWriter;
+
+import org.apache.commons.configuration.XMLConfiguration;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.logging.impl.Log4JLogger;
+import org.apache.log4j.WriterAppender;
+import org.apache.log4j.SimpleLayout;
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+import org.apache.log4j.ConsoleAppender;
+
+/**
+ * Test class for ExprLookup.
+ *
+ * @version $Id: $
+ */
+public class TestExprLookup extends TestCase
+{
+ private static File TEST_FILE = new File("conf/test.xml");
+
+ private static String PATTERN1 =
+ "String.replace(Util.message, 'Hello', 'Goodbye') + System.getProperty('user.name')";
+ private static String PATTERN2 =
+ "'$[element] ' + String.trimToEmpty('$[space.description]')";
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ }
+
+ /**
+ * Clears the test environment. Here the static cache of the constant lookup
+ * class is wiped out.
+ */
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ public void testLookup() throws Exception
+ {
+ ConsoleAppender app = new ConsoleAppender(new SimpleLayout());
+ Log log = LogFactory.getLog("TestLogger");
+ Logger logger = ((Log4JLogger)log).getLogger();
+ logger.addAppender(app);
+ logger.setLevel(Level.DEBUG);
+ logger.setAdditivity(false);
+ ExprLookup.Variables vars = new ExprLookup.Variables();
+ vars.add(new ExprLookup.Variable("String", org.apache.commons.lang.StringUtils.class));
+ vars.add(new ExprLookup.Variable("Util", new Utility("Hello")));
+ vars.add(new ExprLookup.Variable("System", "Class:java.lang.System"));
+ XMLConfiguration config = new XMLConfiguration(TEST_FILE);
+ config.setLogger(log);
+ ExprLookup lookup = new ExprLookup(vars);
+ lookup.setConfiguration(config);
+ String str = lookup.lookup(PATTERN1);
+ assertTrue(str.startsWith("Goodbye"));
+ str = lookup.lookup(PATTERN2);
+ assertTrue("Incorrect value: " + str, str.equals("value Some text"));
+ logger.removeAppender(app);
+
+ }
+
+
+
+ public static class Utility
+ {
+ String message;
+
+ public Utility(String msg)
+ {
+ this.message = msg;
+ }
+
+ public String getMessage()
+ {
+ return message;
+ }
+
+ public String str(String str)
+ {
+ return str;
+ }
+ }
+}
Modified: commons/proper/configuration/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/xdocs/changes.xml?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/xdocs/changes.xml (original)
+++ commons/proper/configuration/trunk/xdocs/changes.xml Sat Apr 11 06:23:13 2009
@@ -23,6 +23,11 @@
<body>
<release version="1.7" date="in SVN" description="">
+ <action dev="rgoers" type="add" issue="CONFIGURATION-380">
+ Add ExprLookup to allow expressions to be evaluated in configurations. When
+ used, this requires that Apache Commons Jexl be added as a dependency to
+ projects using Commons Configuration.
+ </action>
<action dev="oheger" type="add" issue="CONFIGURATION-374">
MapConfiguration now provides a way of controlling the trimming
behavior.
Modified: commons/proper/configuration/trunk/xdocs/userguide/howto_basicfeatures.xml
URL: http://svn.apache.org/viewvc/commons/proper/configuration/trunk/xdocs/userguide/howto_basicfeatures.xml?rev=764168&r1=764167&r2=764168&view=diff
==============================================================================
--- commons/proper/configuration/trunk/xdocs/userguide/howto_basicfeatures.xml (original)
+++ commons/proper/configuration/trunk/xdocs/userguide/howto_basicfeatures.xml Sat Apr 11 06:23:13 2009
@@ -271,7 +271,80 @@
which are then only used by this configuration instance.
</p>
</subsection>
- </section>
+ <subsection name="Using Expressions">
+ <p>
+ In addition to the simple lookup mechanisms previously described, Commond Configuration
+ provides <code>ExprLookup</code> which uses <a href="http://commons.apache.org/jexl">Apache
+ Commons Jexl</a> to allow expressions to be resolved wherever a StrLookup is allowed. This
+ example shows an alternate way of obtaining a system property if the ExprLookup is
+ configured.
+ </p>
+<source><![CDATA[
+user.file = ${expr:System.getProperty("user.home"}/settings.xml
+]]></source>
+ <p>
+ <code>ExprLookup</code> is not enabled by default, it must be manually added or configured via
+ <code>DefaultConfigurationBuilder</code>. Builds that use Maven 2 and reference Commons
+ Configuration will not include a dependency on Jexl, so if this feature is used the
+ dependency on Jexl must be manually added to the project.
+ </p>
+ <p>
+ When using <code>DefaultConfigurationBuilder</code> adding <code>ExprLookup</code> is
+ straightforward.
+ </p>
+<source><![CDATA[
+<configuration>
+ <header>
+ <result/>
+ <lookups>
+ <lookup config-prefix="expr"
+ config-class="org.apache.commons.configuration.interpol.ExprLookup">
+ <variables>
+ <variable name="System" value="Class:java.lang.System"/>
+ <variable name"net" value="Class:java.net.InetAddress"/>
+ <variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
+ </variables>
+ </lookup>
+ </lookups>
+ </header>
+ <override>
+ <xml fileName="${expr:System.getProperty('basePath') +
+ String.lowercase(net.localHost.hostName) + '/testMultiConfiguration_default.xml'}"
+ config-name="defaultConfig" delimiterParsingDisabled="true">
+ </xml>
+ </override>
+</configuration>
+]]></source>
+ <p>
+ The example above shows how to invoke static methods during expression evaluation. The
+ next example shows mixing expression evaluation with a subordinate lookup to
+ obtain the "basePath" system property. Note the difference in how the
+ system property was obtained in the previous example.
+ </p>
+<source><![CDATA[
+<configuration>
+ <header>
+ <result/>
+ <lookups>
+ <lookup config-prefix="expr"
+ config-class="org.apache.commons.configuration.interpol.ExprLookup">
+ <variables>
+ <variable name"net" value="Class:java.net.InetAddress"/>
+ <variable name="String" value="Class:org.apache.commons.lang.StringUtils"/>
+ </variables>
+ </lookup>
+ </lookups>
+ </header>
+ <override>
+ <xml fileName="${expr:$[sys:basePath] +
+ String.lowercase(net.localHost.hostName) + '/testMultiConfiguration_default.xml'}"
+ config-name="defaultConfig" delimiterParsingDisabled="true">
+ </xml>
+ </override>
+</configuration>
+]]></source>
+ </subsection>
+ </section>
</body>
</document>
\ No newline at end of file