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