mirror of https://github.com/apache/openjpa.git
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:
parent
3db7e32a56
commit
264356a23f
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue