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
This commit is contained in:
Patrick Linskey 2006-12-16 23:58:54 +00:00
parent 3db7e32a56
commit 264356a23f
11 changed files with 181 additions and 84 deletions

View File

@ -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,

View File

@ -187,7 +187,7 @@ public abstract class AbstractStoreManager
* Since this store manager does not provide optimistic locking
* support, this method always returns <code>true</code>.
*/
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 <code>subclasses</code>.
* 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 <code>null</code>, 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);

View File

@ -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() {

View File

@ -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]);

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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);
}
/**

View File

@ -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));
}
}

View File

@ -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 <code>key</code>, given the registered
* prefixes and the entries in <code>map</code>. This method
* computes the appropriate configuration prefix to use by looking
* through <code>map</code> for a key starting with any of the known
* configuration prefixes and ending with <code>key</code> 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.

View File

@ -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));
}
}