Skip to content

Instantly share code, notes, and snippets.

@mp911de
Created November 22, 2013 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save mp911de/7600734 to your computer and use it in GitHub Desktop.
Save mp911de/7600734 to your computer and use it in GitHub Desktop.
Cached Apache Commons XML Configuration
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* @author <a href="mailto:mpaluch@paluch.biz">Mark Paluch</a>
* @since 22.11.13 14:48
*/
public abstract class AbstractConfigurationTest
{
@Test
public void testStrings() throws Exception
{
HierarchicalConfiguration configuration = getConfiguration();
long start = System.currentTimeMillis();
int iterations = getIterations();
for (int i = 0; i < iterations; i++)
{
configuration.getString("string");
}
long finish = System.currentTimeMillis();
System.out.println("Duration testStrings: " + (finish - start));
}
@Test
public void testSubnodeConfiguration() throws Exception
{
HierarchicalConfiguration configuration = getConfiguration();
long start = System.currentTimeMillis();
int iterations = getIterations();
for (int i = 0; i < iterations; i++)
{
SubnodeConfiguration subnodeConfiguration = configuration.configurationAt("strings");
int result = subnodeConfiguration.getInt("integer");
assertEquals(1234, result);
}
long finish = System.currentTimeMillis();
System.out.println("Duration testSubnodeConfiguration: " + (finish - start));
}
@Test
public void testInteger() throws Exception
{
HierarchicalConfiguration configuration = getConfiguration();
long start = System.currentTimeMillis();
int iterations = getIterations();
for (int i = 0; i < iterations; i++)
{
configuration.getInt("integer");
}
long finish = System.currentTimeMillis();
System.out.println("Duration testInteger: " + (finish - start));
}
@Test
public void testStringArrays() throws Exception
{
HierarchicalConfiguration configuration = getConfiguration();
long start = System.currentTimeMillis();
int iterations = getIterations();
for (int i = 0; i < iterations; i++)
{
String[] result = configuration.getStringArray("strings/string");
assertEquals(5, result.length);
}
long finish = System.currentTimeMillis();
System.out.println("Duration testStringArrays: " + (finish - start));
}
public abstract HierarchicalConfiguration getConfiguration();
public abstract int getIterations();
}
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.tree.ConfigurationNode;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
public class CachedSubnodeConfiguration extends SubnodeConfiguration implements UnderlyingConfigurationAccessor
{
private transient LoadingCache<String, CacheEntry<Object>> propertyCache;
private transient LoadingCache<ConfigurationNode, SubnodeConfiguration> subnodeCache;
private transient LoadingCache<String, CacheEntry<SubnodeConfiguration>> configurationAtCache;
private transient LoadingCache<String, List<HierarchicalConfiguration>> configurationsAtCache;
private transient LoadingCache<String, CacheEntry<Properties>> propertiesCache;
public CachedSubnodeConfiguration(HierarchicalConfiguration parent, ConfigurationNode root)
{
super(parent, root);
initialize();
}
private void initialize()
{
subnodeCache = createCache(CacheFunctions.loadSubnode(this));
propertyCache = createCache(CacheFunctions.loadProperty(this));
configurationAtCache = createCache(CacheFunctions.loadConfigurationAt(this, this));
configurationsAtCache = createCache(CacheFunctions.loadConfigurationsAt(this, this));
propertiesCache = createCache(CacheFunctions.loadProperties(this));
}
private LoadingCache createCache(Function loadFunction)
{
return CacheBuilder.newBuilder().build(CacheLoader.from(loadFunction));
}
@Override
protected SubnodeConfiguration createSubnodeConfiguration(ConfigurationNode node)
{
try
{
return subnodeCache.get(node);
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public List<HierarchicalConfiguration> configurationsAt(String key)
{
try
{
return configurationsAtCache.get(key);
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public SubnodeConfiguration configurationAt(String key, boolean supportUpdates)
{
try
{
return configurationAtCache.get(key).get();
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public Object getProperty(String key)
{
try
{
return propertyCache.get(key).get();
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public Properties getProperties(String key)
{
try
{
return propertiesCache.get(key).get();
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public Object getUnderlyingProperty(String input)
{
return super.getProperty(input);
}
@Override
public Properties getUnderlyingProperties(String input)
{
return super.getProperties(input);
}
@Override
public List<HierarchicalConfiguration> underlyingConfigurationsAt(String input)
{
return super.configurationsAt(input);
}
@Override
public HierarchicalConfiguration underlyingConfigurationAt(String input)
{
return super.configurationAt(input, false);
}
@Override
protected void subnodeConfigurationChanged(ConfigurationEvent event)
{
super.subnodeConfigurationChanged(event);
subnodeCache.invalidateAll();
propertyCache.invalidateAll();
configurationAtCache.invalidateAll();
configurationsAtCache.invalidateAll();
propertiesCache.invalidateAll();
}
}
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.util.concurrent.UncheckedExecutionException;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.event.ConfigurationEvent;
import org.apache.commons.configuration.tree.ConfigurationNode;
import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.ExecutionException;
public class CachedXmlConfiguration extends XMLConfiguration implements UnderlyingConfigurationAccessor
{
private transient LoadingCache<String, CacheEntry<Object>> propertyCache;
private transient LoadingCache<ConfigurationNode, SubnodeConfiguration> subnodeCache;
private transient LoadingCache<String, CacheEntry<SubnodeConfiguration>> configurationAtCache;
private transient LoadingCache<String, List<HierarchicalConfiguration>> configurationsAtCache;
private transient LoadingCache<String, CacheEntry<Properties>> propertiesCache;
public CachedXmlConfiguration()
{
super();
initialize();
}
public CachedXmlConfiguration(HierarchicalConfiguration c)
{
super(c);
initialize();
}
public CachedXmlConfiguration(String fileName) throws ConfigurationException
{
super(fileName);
initialize();
}
public CachedXmlConfiguration(File file) throws ConfigurationException
{
super(file);
initialize();
}
public CachedXmlConfiguration(URL url) throws ConfigurationException
{
super(url);
initialize();
}
private void initialize()
{
subnodeCache = createCache(CacheFunctions.loadSubnode(this));
propertyCache = createCache(CacheFunctions.loadProperty(this));
configurationAtCache = createCache(CacheFunctions.loadConfigurationAt(this, this));
configurationsAtCache = createCache(CacheFunctions.loadConfigurationsAt(this, this));
propertiesCache = createCache(CacheFunctions.loadProperties(this));
}
private LoadingCache createCache(Function loadFunction)
{
return CacheBuilder.newBuilder().build(CacheLoader.from(loadFunction));
}
@Override
protected SubnodeConfiguration createSubnodeConfiguration(ConfigurationNode node)
{
try
{
return subnodeCache.get(node);
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public List<HierarchicalConfiguration> configurationsAt(String key)
{
try
{
return configurationsAtCache.get(key);
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public SubnodeConfiguration configurationAt(String key, boolean supportUpdates)
{
try
{
return configurationAtCache.get(key).get();
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public Object getProperty(String key)
{
try
{
return propertyCache.get(key).get();
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public Properties getProperties(String key)
{
try
{
return propertiesCache.get(key).get();
} catch (UncheckedExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw e;
} catch (ExecutionException e)
{
if (e.getCause() instanceof RuntimeException)
{
throw (RuntimeException) e.getCause();
}
throw new IllegalStateException(e);
}
}
@Override
public Object getUnderlyingProperty(String input)
{
return super.getProperty(input);
}
@Override
public Properties getUnderlyingProperties(String input)
{
return super.getProperties(input);
}
@Override
public List<HierarchicalConfiguration> underlyingConfigurationsAt(String input)
{
return super.configurationsAt(input);
}
@Override
public HierarchicalConfiguration underlyingConfigurationAt(String input)
{
return super.configurationAt(input, false);
}
@Override
public void configurationChanged(ConfigurationEvent event)
{
super.configurationChanged(event);
subnodeCache.invalidateAll();
propertyCache.invalidateAll();
configurationAtCache.invalidateAll();
configurationsAtCache.invalidateAll();
propertiesCache.invalidateAll();
}
}
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.junit.Before;
/**
* @author <a href="mailto:mpaluch@paluch.biz">Mark Paluch</a>
* @since 22.11.13 14:54
*/
public class CachedXmlConfigurationTest extends AbstractConfigurationTest
{
private HierarchicalConfiguration hierarchicalConfiguration;
@Before
public void before() throws Exception
{
hierarchicalConfiguration = new CachedXmlConfiguration(getClass().getResource("/test-config.xml"));
hierarchicalConfiguration.setExpressionEngine(new XPathExpressionEngine());
}
@Override
public HierarchicalConfiguration getConfiguration()
{
return hierarchicalConfiguration;
}
@Override
public int getIterations()
{
return 1000;
}
}
/**
* @author <a href="mailto:mpaluch@paluch.biz">Mark Paluch</a>
* @since 19.11.13 13:13
*/
public class CacheEntry<T> {
private T object;
public CacheEntry(T object) {
this.object = object;
}
public T get() {
return object;
}
}
import com.google.common.base.Function;
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.SubnodeConfiguration;
import org.apache.commons.configuration.tree.ConfigurationNode;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
public class CacheFunctions
{
private CacheFunctions()
{
}
public static Function<ConfigurationNode, SubnodeConfiguration> loadSubnode(final HierarchicalConfiguration parent)
{
return new Function<ConfigurationNode, SubnodeConfiguration>()
{
@Override
public SubnodeConfiguration apply(ConfigurationNode input)
{
return new CachedSubnodeConfiguration(parent, input);
}
};
}
public static Function<String, CacheEntry<Object>> loadProperty(final UnderlyingConfigurationAccessor datasource)
{
return new Function<String, CacheEntry<Object>>()
{
@Override
public CacheEntry<Object> apply(String input)
{
return new CacheEntry<Object>(datasource.getUnderlyingProperty(input));
}
};
}
public static Function<String, CacheEntry<Properties>> loadProperties(
final UnderlyingConfigurationAccessor datasource)
{
return new Function<String, CacheEntry<Properties>>()
{
@Override
public CacheEntry<Properties> apply(String input)
{
return new CacheEntry<Properties>(datasource.getUnderlyingProperties(input));
}
};
}
public static Function<String, List<HierarchicalConfiguration>> loadConfigurationsAt(
final HierarchicalConfiguration parent, final UnderlyingConfigurationAccessor datasource)
{
return new Function<String, List<HierarchicalConfiguration>>()
{
@Override
public List<HierarchicalConfiguration> apply(String input)
{
List<HierarchicalConfiguration> hierarchicalConfigurations =
datasource.underlyingConfigurationsAt(input);
List<HierarchicalConfiguration> result = new ArrayList<HierarchicalConfiguration>();
for (HierarchicalConfiguration hierarchicalConfiguration : hierarchicalConfigurations)
{
CachedSubnodeConfiguration cachedSubnodeConfiguration =
new CachedSubnodeConfiguration(parent, hierarchicalConfiguration.getRootNode());
result.add(cachedSubnodeConfiguration);
}
return result;
}
};
}
public static Function<String, CacheEntry<SubnodeConfiguration>> loadConfigurationAt(
final HierarchicalConfiguration parent, final UnderlyingConfigurationAccessor datasource)
{
return new Function<String, CacheEntry<SubnodeConfiguration>>()
{
@Override
public CacheEntry<SubnodeConfiguration> apply(String input)
{
HierarchicalConfiguration hierarchicalConfiguration = datasource.underlyingConfigurationAt(input);
SubnodeConfiguration result =
new CachedSubnodeConfiguration(parent, hierarchicalConfiguration.getRootNode());
return new CacheEntry<SubnodeConfiguration>(result);
}
};
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>config</groupId>
<artifactId>config</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>commons-jxpath</groupId>
<artifactId>commons-jxpath</artifactId>
<version>1.3</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
</dependencies>
</project>
<test>
<string>fasdfasdfasdf</string>
<boolean>true</boolean>
<integer>1234</integer>
<strings>
<string>s1</string>
<string>s2</string>
<string>s3</string>
<string>s4</string>
<string>s5</string>
<integer>1234</integer>
</strings>
</test>
import org.apache.commons.configuration.HierarchicalConfiguration;
import java.util.List;
import java.util.Properties;
public interface UnderlyingConfigurationAccessor
{
Object getUnderlyingProperty(String input);
Properties getUnderlyingProperties(String input);
List<HierarchicalConfiguration> underlyingConfigurationsAt(String input);
HierarchicalConfiguration underlyingConfigurationAt(String input);
}
import org.apache.commons.configuration.HierarchicalConfiguration;
import org.apache.commons.configuration.XMLConfiguration;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.junit.Before;
/**
* @author <a href="mailto:mpaluch@paluch.biz">Mark Paluch</a>
* @since 22.11.13 14:54
*/
public class XmlConfigurationTest extends AbstractConfigurationTest
{
private HierarchicalConfiguration hierarchicalConfiguration;
@Before
public void before() throws Exception
{
hierarchicalConfiguration = new XMLConfiguration(getClass().getResource("/test-config.xml"));
hierarchicalConfiguration.setExpressionEngine(new XPathExpressionEngine());
}
@Override
public HierarchicalConfiguration getConfiguration()
{
return hierarchicalConfiguration;
}
@Override
public int getIterations()
{
return 1000;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment