From 264356a23f3044a9e67d76aa47cd437dacdf5276 Mon Sep 17 00:00:00 2001 From: Patrick Linskey Date: Sat, 16 Dec 2006 23:58:54 +0000 Subject: [PATCH] created methods for interacting with product prefixes; moved configuration loading mechanisms to these new methods git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@487919 13f79535-47bb-0310-9956-ffa450edef68 --- .../AbstractStoreBrokerFactory.java | 8 +- .../abstractstore/AbstractStoreManager.java | 17 ++-- .../openjpa/conf/BrokerFactoryValue.java | 13 +-- .../conf/OpenJPAConfigurationImpl.java | 18 ++-- .../conf/OpenJPAProductDerivation.java | 2 +- .../apache/openjpa/kernel/StoreManager.java | 2 +- .../apache/openjpa/meta/ValueMetaData.java | 4 +- .../openjpa/lib/conf/ConfigurationImpl.java | 26 ++---- .../openjpa/lib/conf/Configurations.java | 36 +++----- .../openjpa/lib/conf/ProductDerivations.java | 54 +++++++++++- .../TestConfigurationProviderPrefixes.java | 85 +++++++++++++++++++ 11 files changed, 181 insertions(+), 84 deletions(-) create mode 100644 openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurationProviderPrefixes.java diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreBrokerFactory.java b/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreBrokerFactory.java index c07a24098..eeb1e493a 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreBrokerFactory.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreBrokerFactory.java @@ -25,6 +25,7 @@ import org.apache.openjpa.kernel.BrokerFactory; import org.apache.openjpa.kernel.StoreManager; import org.apache.openjpa.lib.conf.ConfigurationProvider; import org.apache.openjpa.lib.conf.Configurations; +import org.apache.openjpa.lib.conf.ProductDerivations; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.util.UserException; @@ -51,8 +52,8 @@ public class AbstractStoreBrokerFactory * The property name under which to name the concrete store manager * class for this runtime. */ - public static final String PROP_ABSTRACT_STORE = - "org.apache.openjpa.abstractstore.AbstractStoreManager"; + private static final String PROP_ABSTRACT_STORE = + "abstractstore.AbstractStoreManager"; private static final Localizer s_loc = Localizer.forPackage (AbstractStoreBrokerFactory.class); @@ -86,7 +87,8 @@ public class AbstractStoreBrokerFactory // use a tmp store manager to get metadata about the capabilities of // this runtime Map map = cp.getProperties(); - String storePlugin = (String) map.get(PROP_ABSTRACT_STORE); + String storePlugin = (String) map.get(ProductDerivations + .getConfigurationKey(PROP_ABSTRACT_STORE, map)); String storeCls = Configurations.getClassName(storePlugin); String storeProps = Configurations.getProperties(storePlugin); AbstractStoreManager store = createStoreManager(storeCls, diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java index a1277e71e..431d30185 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java @@ -187,7 +187,7 @@ public abstract class AbstractStoreManager * Since this store manager does not provide optimistic locking * support, this method always returns true. */ - public boolean syncVersion(OpenJPAStateManager sm, Object context) { + public boolean syncVersion(OpenJPAStateManager sm, Object edata) { return true; } @@ -210,7 +210,7 @@ public abstract class AbstractStoreManager * data into the object. */ public abstract boolean initialize(OpenJPAStateManager sm, PCState state, - FetchConfiguration fetch, Object context); + FetchConfiguration fetch, Object edata); /** * This method is invoked when OpenJPA needs to load additional data @@ -222,7 +222,7 @@ public abstract class AbstractStoreManager * data into the object. */ public abstract boolean load(OpenJPAStateManager sm, BitSet fields, - FetchConfiguration fetch, int lockLevel, Object context); + FetchConfiguration fetch, int lockLevel, Object edata); /** * This implementation just delegates to the proper singular @@ -232,8 +232,8 @@ public abstract class AbstractStoreManager * advantageous. */ public Collection loadAll(Collection sms, PCState state, int load, - FetchConfiguration fetch, Object context) { - return ImplHelper.loadAll(sms, this, state, load, fetch, context); + FetchConfiguration fetch, Object edata) { + return ImplHelper.loadAll(sms, this, state, load, fetch, edata); } /** @@ -362,19 +362,18 @@ public abstract class AbstractStoreManager * by subclasses. * The implementation of the result provider will typically execute * some sort of data store query to find all the applicable objects, loop - * through the returned data, extracting object IDs from the data, and - * invoking + * through the results, extracting object IDs from the data, and invoke * {@link StoreContext#find(Object,FetchConfiguration,BitSet,Object,int)} * on each OID. When invoking this method, the first argument is the OID. * The second is the given fetch configuration. The * third argument is a mask of fields to exclude from loading; it will - * typically be null. The last argument is an object that will be passed + * typically be null. The fourth argument is an object that will be passed * through to {@link #initialize} or {@link #load}, and typically will * contain the actual data to load. For example, for a JDBC-based store * manager, this might be the result set that is being iterated over. If * this argument is null, then the {@link #initialize} or * {@link #load} method will have to issue another command to the data - * store in order to fetch the data to be loaded. + * store in order to fetch the data to be loaded. */ public abstract ResultObjectProvider executeExtent(ClassMetaData meta, boolean subs, FetchConfiguration fetch); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/BrokerFactoryValue.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/BrokerFactoryValue.java index 066f21438..3e4c28456 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/BrokerFactoryValue.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/BrokerFactoryValue.java @@ -64,22 +64,17 @@ public class BrokerFactoryValue * Extract the value of this property if set in the given provider. */ public static Object get(ConfigurationProvider cp) { - String[] prefixes = ProductDerivations.getConfigurationPrefixes(); Map props = cp.getProperties(); - Object bf; - for (int i = 0; i < prefixes.length; i++) { - bf = props.get(prefixes[i] + "." + KEY); - if (bf != null) - return bf; - } - return null; + return props.get(ProductDerivations.getConfigurationKey(KEY, props)); } /** * Set the value of this property in the given provider. */ public static void set(ConfigurationProvider cp, String value) { - cp.addProperty("openjpa." + KEY, value); + String key = ProductDerivations.getConfigurationKey(KEY, + cp.getProperties()); + cp.addProperty(key, value); } public BrokerFactoryValue() { diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java index ad5431282..3c9515cac 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java @@ -193,10 +193,11 @@ public class OpenJPAConfigurationImpl dataCacheManagerPlugin.setInstantiatingGetter("getDataCacheManager"); dataCachePlugin = addPlugin("DataCache", false); - aliases = - new String[] { "false", null, "true", - ConcurrentDataCache.class.getName(), "concurrent", - ConcurrentDataCache.class.getName(), }; + aliases = new String[] { + "false", null, + "true", ConcurrentDataCache.class.getName(), + "concurrent", ConcurrentDataCache.class.getName(), + }; dataCachePlugin.setAliases(aliases); dataCachePlugin.setDefault(aliases[0]); dataCachePlugin.setString(aliases[0]); @@ -206,10 +207,11 @@ public class OpenJPAConfigurationImpl dataCacheTimeout.set(-1); queryCachePlugin = addPlugin("QueryCache", true); - aliases = - new String[] { "true", ConcurrentQueryCache.class.getName(), - "concurrent", ConcurrentQueryCache.class.getName(), "false", - null, }; + aliases = new String[] { + "true", ConcurrentQueryCache.class.getName(), + "concurrent", ConcurrentQueryCache.class.getName(), + "false", null, + }; queryCachePlugin.setAliases(aliases); queryCachePlugin.setDefault(aliases[0]); queryCachePlugin.setString(aliases[0]); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAProductDerivation.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAProductDerivation.java index 487e4e758..7ff47a2e5 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAProductDerivation.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAProductDerivation.java @@ -33,7 +33,7 @@ public interface OpenJPAProductDerivation extends ProductDerivation { /** * Load default alias options into the given map. Each entry maps an - * alias to a broker factory class name. Replace anything perviously + * alias to a broker factory class name. Replace anything previously * under the desired keys. */ public void putBrokerFactoryAliases(Map aliases); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java index 376aff12f..714153c7c 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java @@ -141,7 +141,7 @@ public interface StoreManager /** * Load the given state manager. * Note that any collection or map types loaded into the state manager - * will be proxied with the correct type; therefore the stroe manager + * will be proxied with the correct type; therefore the store manager * does not have to load the same concrete collection/map types as the * instance declares. However, array types must be consistent with the * array type stored by the persistence capable instance. If this method diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaData.java index 547421992..2e97b1ab7 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ValueMetaData.java @@ -296,7 +296,7 @@ public interface ValueMetaData /** * Copy state from the given value to this one. Do not copy mapping - * information. + * information. */ - public void copy (ValueMetaData vmd); + public void copy(ValueMetaData vmd); } diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java index c01c80388..1c649f24b 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ConfigurationImpl.java @@ -665,27 +665,11 @@ public class ConfigurationImpl * Look up the given value, testing all available prefixes. */ private Object get(Map map, Value val, boolean setLoadKey) { - String[] prefixes = ProductDerivations.getConfigurationPrefixes(); - String firstKey = null; - String key; - Object o = null; - for (int i = 0; i < prefixes.length; i++) { - key = prefixes[i] + "." + val.getProperty(); - if (firstKey == null) { - o = map.get(key); - if (o != null) - firstKey = key; - } else if (map.containsKey(key)) { - // if we've already found a property with a previous prefix, - // then this is a collision. - throw new IllegalStateException( - _loc.get("dup-with-different-prefixes", firstKey, key) - .getMessage()); - } - } - if (firstKey != null && setLoadKey) - val.setLoadKey(firstKey); - return o; + String key = ProductDerivations.getConfigurationKey( + val.getProperty(), map); + if (map.containsKey(key) && setLoadKey) + val.setLoadKey(key); + return map.get(key); } /** diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configurations.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configurations.java index 10ec4bba2..b3317a508 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configurations.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/Configurations.java @@ -513,30 +513,22 @@ public class Configurations { * configuration prefix. */ public static boolean containsProperty(String key, Map props) { - if (key == null || props == null) + if (key == null || props == null || props.isEmpty()) return false; - String[] prefixes = ProductDerivations.getConfigurationPrefixes(); - for (int i = 0; i < prefixes.length; i++) - if (props.containsKey(prefixes[i] + "." + key)) - return true; - return false; + else + return props.containsKey( + ProductDerivations.getConfigurationKey(key, props)); } /** * Get the property under the given key, prefixed with any possible * configuration prefix. */ - public static Object getProperty(String key, Map props) { - if (key == null || props == null) + public static Object getProperty(String key, Map m) { + if (key == null || m == null || m.isEmpty()) return null; - String[] prefixes = ProductDerivations.getConfigurationPrefixes(); - Object val; - for (int i = 0; i < prefixes.length; i++) { - val = props.get(prefixes[i] + "." + key); - if (val != null) - return val; - } - return null; + else + return m.get(ProductDerivations.getConfigurationKey(key, m)); } /** @@ -544,16 +536,8 @@ public class Configurations { * configuration prefix. */ public static Object removeProperty(String key, Map props) { - if (key == null || props == null) + if (key == null || props == null || props.isEmpty()) return null; - String[] prefixes = ProductDerivations.getConfigurationPrefixes(); - Object val = null; - Object cur; - for (int i = 0; i < prefixes.length; i++) { - cur = props.remove(prefixes[i] + "." + key); - if (cur != null && val == null) - val = cur; - } - return val; + return props.remove(ProductDerivations.getConfigurationKey(key, props)); } } diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ProductDerivations.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ProductDerivations.java index d5a96001e..6c53ea4e9 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ProductDerivations.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/conf/ProductDerivations.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.MissingResourceException; import org.apache.commons.lang.StringUtils; @@ -40,7 +41,7 @@ public class ProductDerivations { private static final ProductDerivation[] _derivations; private static final String[] _derivationNames; private static final Throwable[] _derivationErrors; - private static final String[] _prefixes; + private static String[] _prefixes; static { ClassLoader l = ProductDerivation.class.getClassLoader(); _derivationNames = Services.getImplementors(ProductDerivation.class, l); @@ -85,10 +86,11 @@ public class ProductDerivations { && !"openjpa".equals(_derivations[i].getConfigurationPrefix())) prefixes.add(_derivations[i].getConfigurationPrefix()); } - _prefixes = new String[1 + prefixes.size()]; - _prefixes[0] = "openjpa"; + String[] prefixArray = new String[1 + prefixes.size()]; + prefixArray[0] = "openjpa"; for (int i = 0; i < prefixes.size(); i++) - _prefixes[i + 1] = (String) prefixes.get(i); + prefixArray[i + 1] = (String) prefixes.get(i); + setConfigurationPrefixes(prefixArray); } /** @@ -105,6 +107,50 @@ public class ProductDerivations { return _prefixes; } + /** + * Set the configuration prefix array. This is package-visible for + * testing purposes. + * + * @since 0.9.7 + */ + static void setConfigurationPrefixes(String[] prefixes) { + _prefixes = prefixes; + } + + /** + * Determine the full key name for key, given the registered + * prefixes and the entries in map. This method + * computes the appropriate configuration prefix to use by looking + * through map for a key starting with any of the known + * configuration prefixes and ending with key and, if a + * value is found, using the prefix of that key. Otherwise, it uses + * the first registered prefix. + * + * @since 0.9.7 + */ + public static String getConfigurationKey(String partialKey, Map map) { + String firstKey = null; + for (int i = 0; map != null && i < _prefixes.length; i++) { + String fullKey = _prefixes[i] + "." + partialKey; + if (map.containsKey(fullKey)) { + if (firstKey == null) + firstKey = fullKey; + else { + // if we've already found a property with a previous + // prefix, then this is a collision. + throw new IllegalStateException(_loc.get( + "dup-with-different-prefixes", firstKey, fullKey) + .getMessage()); + } + } + } + + if (firstKey == null) + return _prefixes[0] + "." + partialKey; + else + return firstKey; + } + /** * Apply {@link ProductDerivation#beforeConfigurationConstruct} callbacks * to the the given instance. Exceptions are swallowed. diff --git a/openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurationProviderPrefixes.java b/openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurationProviderPrefixes.java new file mode 100644 index 000000000..5b2b3967a --- /dev/null +++ b/openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurationProviderPrefixes.java @@ -0,0 +1,85 @@ +package org.apache.openjpa.lib.conf; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; + + +public class TestConfigurationProviderPrefixes + extends TestCase { + + private static final String CUSTOM_PREFIX = + TestConfigurationProviderPrefixes.class.getName(); + + private String[] _origPrefixes; + + public void setUp() { + _origPrefixes = ProductDerivations.getConfigurationPrefixes(); + List l = new ArrayList(Arrays.asList(_origPrefixes)); + l.add(CUSTOM_PREFIX); + ProductDerivations.setConfigurationPrefixes( + (String[]) l.toArray(new String[0])); + } + + public void tearDown() { + ProductDerivations.setConfigurationPrefixes(_origPrefixes); + } + + public void testPrefixContents() { + String[] prefixes = ProductDerivations.getConfigurationPrefixes(); + assertEquals(CUSTOM_PREFIX, prefixes[prefixes.length - 1]); + assertEquals("openjpa", prefixes[0]); + } + + public void testPartialKeyAndNullMap() { + assertEquals("openjpa.Foo", "Foo", (Map) null, null); + } + + public void testPartialKeyWithInvalidPrefix() { + Map map = new HashMap(); + map.put("bar.Foo", "value"); + assertEquals("openjpa.Foo", "Foo", map, null); + } + + public void testPartialKeyWithoutMatch() { + Map map = new HashMap(); + map.put("bar.Baz", "value"); + assertEquals("openjpa.Foo", "Foo", map, null); + } + + public void testPartialKeyWithOpenJPAMatch() { + Map map = new HashMap(); + map.put("openjpa.Foo", "value"); + assertEquals("openjpa.Foo", "Foo", map, "value"); + } + + public void testPartialKeyWithCustomMatch() { + Map map = new HashMap(); + map.put(CUSTOM_PREFIX + ".Foo", "value"); + assertEquals(CUSTOM_PREFIX + ".Foo", "Foo", map, "value"); + } + + public void testPartialKeyDuplicateFullKeys() { + Map map = new HashMap(); + map.put(CUSTOM_PREFIX + ".Foo", "value"); + map.put("openjpa.Foo", "value"); + try { + ProductDerivations.getConfigurationKey("Foo", map); + fail("duplicate keys should result in an IllegalStateException"); + } catch (IllegalStateException e) { + // expected + } + } + + private static void assertEquals(String fullKey, String partialKey, + Map map, Object value) { + assertEquals(fullKey, ProductDerivations.getConfigurationKey( + partialKey, map)); + if (map != null) + assertEquals(value, map.get(fullKey)); + } +}