You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by oh...@apache.org on 2006/12/26 22:28:05 UTC
svn commit: r490375 - in /jakarta/commons/proper/configuration/trunk/src:
java/org/apache/commons/configuration/interpol/
test/org/apache/commons/configuration/interpol/
Author: oheger
Date: Tue Dec 26 13:28:04 2006
New Revision: 490375
URL: http://svn.apache.org/viewvc?view=rev&rev=490375
Log:
CONFIGURATION-192: Added new ConstantLookup class for resolving variables that refer to final static member fields of classes
Added:
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java (with props)
jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java (with props)
Modified:
jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConfigurationInterpolator.java
jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConfigurationInterpolator.java
Modified: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConfigurationInterpolator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConfigurationInterpolator.java?view=diff&rev=490375&r1=490374&r2=490375
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConfigurationInterpolator.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConfigurationInterpolator.java Tue Dec 26 13:28:04 2006
@@ -86,7 +86,6 @@
* <code>Configuration</conde>
* object and used for its interpolation tasks.</p>
*
- * @author Oliver Heger
* @version $Id$
* @since 1.4
* @author <a
@@ -101,6 +100,12 @@
*/
public static final String PREFIX_SYSPROPERTIES = "sys";
+ /**
+ * Constant for the prefix of the standard lookup object for resolving
+ * constant values.
+ */
+ public static final String PREFIX_CONSTANTS = "const";
+
/** Constant for the prefix separator. */
private static final char PREFIX_SEPARATOR = ':';
@@ -313,5 +318,6 @@
globalLookups = new HashMap();
globalLookups.put(PREFIX_SYSPROPERTIES, StrLookup
.systemPropertiesLookup());
+ globalLookups.put(PREFIX_CONSTANTS, new ConstantLookup());
}
}
Added: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java?view=auto&rev=490375
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java Tue Dec 26 13:28:04 2006
@@ -0,0 +1,172 @@
+/*
+ * 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 java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.lang.text.StrLookup;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * <p>
+ * A specialized lookup implementation that allows access to constant fields of
+ * classes.
+ * </p>
+ * <p>
+ * Sometimes it is necessary in a configuration file to refer to a constant
+ * defined in a class. This can be done with this lookup implementation.
+ * Variable names passed in must be of the form
+ * <code>mypackage.MyClass.FIELD</code>. The <code>lookup()</code> method
+ * will split the passed in string at the last dot, separating the fully
+ * qualified class name and the name of the constant (i.e. <strong>static final</strong>)
+ * member field. Then the class is loaded and the field's value is obtained
+ * using reflection.
+ * </p>
+ * <p>
+ * Once retrieved values are cached for fast access. This class is thread-safe.
+ * It can be used as a standard (i.e. global) lookup object and serve multiple
+ * clients concurrently.
+ * </p>
+ *
+ * @version $Id$
+ * @since 1.4
+ * @author <a
+ * href="http://jakarta.apache.org/commons/configuration/team-list.html">Commons
+ * Configuration team</a>
+ */
+public class ConstantLookup extends StrLookup
+{
+ /** Constant for the field separator. */
+ private static final char FIELD_SEPRATOR = '.';
+
+ /** An internally used cache for already retrieved values. */
+ private static Map constantCache = new HashMap();
+
+ /** The logger. */
+ private Log log = LogFactory.getLog(getClass());
+
+ /**
+ * Tries to resolve the specified variable. The passed in variable name is
+ * interpreted as the name of a <b>static final</b> member field of a
+ * class. If the value has already been obtained, it can be retrieved from
+ * an internal cache. Otherwise this method will invoke the
+ * <code>resolveField()</code> method and pass in the name of the class
+ * and the field.
+ *
+ * @param var the name of the variable to be resolved
+ * @return the value of this variable or <b>null</b> if it cannot be
+ * resolved
+ */
+ public String lookup(String var)
+ {
+ if (var == null)
+ {
+ return null;
+ }
+
+ String result;
+ synchronized (constantCache)
+ {
+ result = (String) constantCache.get(var);
+ }
+ if (result != null)
+ {
+ return result;
+ }
+
+ int fieldPos = var.lastIndexOf(FIELD_SEPRATOR);
+ if (fieldPos < 0)
+ {
+ return null;
+ }
+ try
+ {
+ Object value = resolveField(var.substring(0, fieldPos), var
+ .substring(fieldPos + 1));
+ if (value != null)
+ {
+ synchronized (constantCache)
+ {
+ // In worst case, the value will be fetched multiple times
+ // because of this lax synchronisation, but for constant
+ // values
+ // this shouldn't be a problem.
+ constantCache.put(var, value);
+ }
+ result = value.toString();
+ }
+ }
+ catch (Exception ex)
+ {
+ log.warn("Could not obtain value for variable " + var, ex);
+ }
+
+ return result;
+ }
+
+ /**
+ * Clears the shared cache with the so far resolved constants.
+ */
+ public static void clear()
+ {
+ synchronized (constantCache)
+ {
+ constantCache.clear();
+ }
+ }
+
+ /**
+ * Determines the value of the specified constant member field of a class.
+ * This implementation will call <code>fetchClass()</code> to obtain the
+ * <code>java.lang.Class</code> object for the target class. Then it will
+ * use reflection to obtain the field's value. For this to work the field
+ * must be accessable.
+ *
+ * @param className the name of the class
+ * @param fieldName the name of the member field of that class to read
+ * @return the field's value
+ * @throws Exception if an error occurs
+ */
+ protected Object resolveField(String className, String fieldName)
+ throws Exception
+ {
+ Class clazz = fetchClass(className);
+ Field field = clazz.getField(fieldName);
+ return field.get(null);
+ }
+
+ /**
+ * Loads the class with the specified name. If an application has special
+ * needs regarding the class loaders to be used, it can hook in here. This
+ * implementation delegates to the <code>getClass()</code> method of
+ * Commons Lang's
+ * <code><a href="http://jakarta.apache.org/commons/lang/api-release/org/apache/commons/lang/ClassUtils.html">
+ * ClassUtils</a></code>.
+ *
+ * @param className the name of the class to be loaded
+ * @return the corresponding class object
+ * @throws ClassNotFoundException if the class cannot be loaded
+ */
+ protected Class fetchClass(String className) throws ClassNotFoundException
+ {
+ return ClassUtils.getClass(className);
+ }
+}
Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: jakarta/commons/proper/configuration/trunk/src/java/org/apache/commons/configuration/interpol/ConstantLookup.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConfigurationInterpolator.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConfigurationInterpolator.java?view=diff&rev=490375&r1=490374&r2=490375
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConfigurationInterpolator.java (original)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConfigurationInterpolator.java Tue Dec 26 13:28:04 2006
@@ -323,4 +323,17 @@
+ ":" + key));
}
}
+
+ /**
+ * Tests whether constants can be correctly resolved.
+ */
+ public void testLookupConstants()
+ {
+ String varName = ConfigurationInterpolator.class.getName()
+ + ".PREFIX_CONSTANTS";
+ assertEquals("Wrong constant value",
+ ConfigurationInterpolator.PREFIX_CONSTANTS, interpolator
+ .lookup(ConfigurationInterpolator.PREFIX_CONSTANTS
+ + ":" + varName));
+ }
}
Added: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java
URL: http://svn.apache.org/viewvc/jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java?view=auto&rev=490375
==============================================================================
--- jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java (added)
+++ jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java Tue Dec 26 13:28:04 2006
@@ -0,0 +1,123 @@
+/*
+ * 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;
+
+/**
+ * Test class for ConstantLookup.
+ *
+ * @version $Id$
+ */
+public class TestConstantLookup extends TestCase
+{
+ /** Constant for the name of the test class. */
+ private static final String CLS_NAME = ConfigurationInterpolator.class
+ .getName() + '.';
+
+ /** Constant for the name of the test field. */
+ private static final String FIELD = "PREFIX_CONSTANTS";
+
+ /** Constant for the test variable name. */
+ private static final String VARNAME = CLS_NAME + FIELD;
+
+ /** The lookup object to be tested. */
+ private ConstantLookup lookup;
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ lookup = new ConstantLookup();
+ }
+
+ /**
+ * Clears the test environment. Here the static cache of the constant lookup
+ * class is wiped out.
+ */
+ protected void tearDown() throws Exception
+ {
+ ConstantLookup.clear();
+ super.tearDown();
+ }
+
+ /**
+ * Tests resolving a valid constant.
+ */
+ public void testLookupConstant()
+ {
+ assertEquals("Wrong value of constant",
+ ConfigurationInterpolator.PREFIX_CONSTANTS, lookup
+ .lookup(VARNAME));
+ }
+
+ /**
+ * Tests resolving a non existing constant. Result should be null.
+ */
+ public void testLookupNonExisting()
+ {
+ assertNull("Non null return value for non existing constant", lookup
+ .lookup(CLS_NAME + "NO_FIELD"));
+ }
+
+ /**
+ * Tests resolving a private constant. Because a private field cannot be
+ * accessed this should again yield null.
+ */
+ public void testLookupPrivate()
+ {
+ assertNull("Non null return value for non accessable field", lookup
+ .lookup(CLS_NAME + "PREFIX_SEPARATOR"));
+ }
+
+ /**
+ * Tests resolving a field from an unknown class.
+ */
+ public void testLookupUnknownClass()
+ {
+ assertNull("Non null return value for unknown class", lookup
+ .lookup("org.apache.commons.configuration.NonExistingConfig."
+ + FIELD));
+ }
+
+ /**
+ * Tries to resolve a variable with an invalid syntax: The name does not
+ * contain a dot as a field separator.
+ */
+ public void testLookupInvalidSyntax()
+ {
+ assertNull("Non null return value for invalid variable name", lookup
+ .lookup("InvalidVariableName"));
+ }
+
+ /**
+ * Tests looking up a null variable.
+ */
+ public void testLookupNull()
+ {
+ assertNull("Non null return value for null variable", lookup
+ .lookup(null));
+ }
+
+ /**
+ * Tests accessing the cache by querying a variable twice.
+ */
+ public void testLookupCache()
+ {
+ testLookupConstant();
+ testLookupConstant();
+ }
+}
Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java
------------------------------------------------------------------------------
svn:keywords = Date Author Id Revision HeadURL
Propchange: jakarta/commons/proper/configuration/trunk/src/test/org/apache/commons/configuration/interpol/TestConstantLookup.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org