Compare Configuration instances on their full properties, including defaults.

Also serialize the full properties because product derivations aren't re-run
on deserialize, so we need to know the complete defaults, etc.  We still track
the user-given properties separately so they can be used in factory pooling.



git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@507643 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2007-02-14 17:53:13 +00:00
parent 611932c86b
commit 7a2330ce3b
2 changed files with 58 additions and 46 deletions

View File

@ -58,8 +58,7 @@ public abstract class AbstractBrokerFactory
(AbstractBrokerFactory.class); (AbstractBrokerFactory.class);
// static mapping of configurations to pooled broker factories // static mapping of configurations to pooled broker factories
private static final Map _pool = Collections.synchronizedMap private static final Map _pool = Collections.synchronizedMap(new HashMap());
(new HashMap());
// configuration // configuration
private final OpenJPAConfiguration _conf; private final OpenJPAConfiguration _conf;
@ -95,6 +94,11 @@ public abstract class AbstractBrokerFactory
return (AbstractBrokerFactory) _pool.get(toPoolKey(conf)); return (AbstractBrokerFactory) _pool.get(toPoolKey(conf));
} }
/**
* Return an internal factory pool key for the given configuration.
* We use the conf properties as given by the user because that is what's
* passed to {@link #getPooledFactory} when looking for an existing factory.
*/
private static Map toPoolKey(OpenJPAConfiguration conf) { private static Map toPoolKey(OpenJPAConfiguration conf) {
return conf.toProperties(false); return conf.toProperties(false);
} }

View File

@ -107,6 +107,7 @@ public class ConfigurationImpl
private String _product = null; private String _product = null;
private boolean _readOnly = false; private boolean _readOnly = false;
private Map _props = null; private Map _props = null;
private Map _fullProps = null;
private boolean _globals = false; private boolean _globals = false;
private String _auto = null; private String _auto = null;
private final List _vals = new ArrayList(); private final List _vals = new ArrayList();
@ -310,7 +311,7 @@ public class ConfigurationImpl
} }
public void valueChanged(Value val) { public void valueChanged(Value val) {
if (_changeSupport == null && _props == null) if (_changeSupport == null && _props == null && _fullProps == null)
return; return;
String newString = val.getString(); String newString = val.getString();
@ -319,12 +320,15 @@ public class ConfigurationImpl
newString); newString);
// keep cached props up to date // keep cached props up to date
if (_props != null) { if (newString == null) {
if (newString == null) Configurations.removeProperty(val.getProperty(), _props);
Configurations.removeProperty(val.getProperty(), _props); Configurations.removeProperty(val.getProperty(), _fullProps);
else if (Configurations.containsProperty(val.getProperty(), _props) } else {
|| val.getDefault() == null put(_fullProps, val, newString);
if (_props != null && _props != _fullProps
&& (val.getDefault() == null
|| !val.getDefault().equals(newString)) || !val.getDefault().equals(newString))
|| Configurations.containsProperty(val.getProperty(), _props))
put(_props, val, newString); put(_props, val, newString);
} }
} }
@ -566,33 +570,30 @@ public class ConfigurationImpl
// clone properties before making any modifications; we need to keep // clone properties before making any modifications; we need to keep
// the internal properties instance consistent to maintain equals and // the internal properties instance consistent to maintain equals and
// hashcode contracts // hashcode contracts
Map map = (storeDefaults) ? _fullProps : _props;
Map clone; Map clone;
if (_props == null) if (map == null)
clone = new HashMap(); clone = new HashMap();
else if (_props instanceof Properties) else if (map instanceof Properties)
clone = (Map) ((Properties) _props).clone(); clone = (Map) ((Properties) map).clone();
else else
clone = new HashMap(_props); clone = new HashMap(map);
// if no existing properties or the properties should contain entries if (map == null) {
// with default values, add values to properties
if (_props == null || storeDefaults) {
Value val; Value val;
String str; String str;
for (int i = 0; i < _vals.size(); i++) { for (int i = 0; i < _vals.size(); i++) {
// if key in existing properties, we already know value is up
// to date
val = (Value) _vals.get(i); val = (Value) _vals.get(i);
if (_props != null && Configurations.containsProperty
(val.getProperty(), _props))
continue;
str = val.getString(); str = val.getString();
if (str != null && (storeDefaults if (str != null && (storeDefaults
|| !str.equals(val.getDefault()))) || !str.equals(val.getDefault())))
put(clone, val, str); put(clone, val, str);
} }
if (_props == null) if (storeDefaults) {
_fullProps = new HashMap(clone);
if (_props == null)
_props = _fullProps;
} else
_props = new HashMap(clone); _props = new HashMap(clone);
} }
return clone; return clone;
@ -605,15 +606,13 @@ public class ConfigurationImpl
// if the only previous call was to load defaults, forget them. // if the only previous call was to load defaults, forget them.
// this way we preserve the original formatting of the user's props // this way we preserve the original formatting of the user's props
// instead of the defaults. this is important for caching on // instead of the defaults.
// configuration objects
if (_globals) { if (_globals) {
_props = null; _props = null;
_globals = false; _globals = false;
} }
Map remaining = new HashMap(map); Map remaining = new HashMap(map);
boolean ser = true;
Value val; Value val;
Object o; Object o;
for (int i = 0; i < _vals.size(); i++) { for (int i = 0; i < _vals.size(); i++) {
@ -625,10 +624,8 @@ public class ConfigurationImpl
if (o instanceof String) { if (o instanceof String) {
if (!StringUtils.equals((String) o, val.getString())) if (!StringUtils.equals((String) o, val.getString()))
val.setString((String) o); val.setString((String) o);
} else { } else
ser &= o instanceof Serializable;
val.setObject(o); val.setObject(o);
}
Configurations.removeProperty(val.getProperty(), remaining); Configurations.removeProperty(val.getProperty(), remaining);
} }
@ -639,16 +636,15 @@ public class ConfigurationImpl
// now warn if there are any remaining properties that there // now warn if there are any remaining properties that there
// is an unhandled prop // is an unhandled prop
Map.Entry entry; String key;
for (Iterator itr = remaining.entrySet().iterator(); itr.hasNext();) { for (Iterator itr = remaining.keySet().iterator(); itr.hasNext();) {
entry = (Map.Entry) itr.next(); key = (String) itr.next();
if (entry.getKey() != null) if (key != null)
warnInvalidProperty((String) entry.getKey()); warnInvalidProperty(key);
ser &= entry.getValue() instanceof Serializable;
} }
// cache properties // cache user-formatted properties
if (_props == null && ser) if (_props == null || _props == _fullProps)
_props = map; _props = map;
} }
@ -658,6 +654,8 @@ public class ConfigurationImpl
* this will account for the property prefix. * this will account for the property prefix.
*/ */
private void put(Map map, Value val, Object o) { private void put(Map map, Value val, Object o) {
if (map == null)
return;
Object key = val.getLoadKey(); Object key = val.getLoadKey();
if (key == null) if (key == null)
key = "openjpa." + val.getProperty(); key = "openjpa." + val.getProperty();
@ -668,6 +666,8 @@ public class ConfigurationImpl
* Look up the given value, testing all available prefixes. * Look up the given value, testing all available prefixes.
*/ */
private Object get(Map map, Value val, boolean setLoadKey) { private Object get(Map map, Value val, boolean setLoadKey) {
if (map == null)
return null;
String key = ProductDerivations.getConfigurationKey( String key = ProductDerivations.getConfigurationKey(
val.getProperty(), map); val.getProperty(), map);
if (map.containsKey(key) && setLoadKey) if (map.containsKey(key) && setLoadKey)
@ -791,8 +791,9 @@ public class ConfigurationImpl
// compare properties // compare properties
ConfigurationImpl conf = (ConfigurationImpl) other; ConfigurationImpl conf = (ConfigurationImpl) other;
Map p1 = (_props == null) ? toProperties(false) : _props; Map p1 = (_fullProps == null) ? toProperties(true) : _fullProps;
Map p2 = (conf._props == null) ? conf.toProperties(false) : conf._props; Map p2 = (conf._fullProps == null) ? conf.toProperties(true)
: conf._fullProps;
return p1.equals(p2); return p1.equals(p2);
} }
@ -801,9 +802,9 @@ public class ConfigurationImpl
* {@link #toProperties}. * {@link #toProperties}.
*/ */
public int hashCode() { public int hashCode() {
if (_props != null) if (_fullProps != null)
return _props.hashCode(); return _fullProps.hashCode();
return toProperties(false).hashCode(); return toProperties(true).hashCode();
} }
/** /**
@ -849,7 +850,11 @@ public class ConfigurationImpl
*/ */
public void readExternal(ObjectInput in) public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException { throws IOException, ClassNotFoundException {
fromProperties((Map) in.readObject()); Map fullProps = (Map) in.readObject();
Map props = (Map) in.readObject();
fromProperties(fullProps);
_fullProps = fullProps;
_props = props;
_globals = in.readBoolean(); _globals = in.readBoolean();
} }
@ -858,10 +863,11 @@ public class ConfigurationImpl
* the properties returned by {@link #toProperties}. * the properties returned by {@link #toProperties}.
*/ */
public void writeExternal(ObjectOutput out) throws IOException { public void writeExternal(ObjectOutput out) throws IOException {
if (_props != null) if (_fullProps != null)
out.writeObject(_props); out.writeObject(_fullProps);
else else
out.writeObject(toProperties(false)); out.writeObject(toProperties(true));
out.writeObject(_props);
out.writeBoolean(_globals); out.writeBoolean(_globals);
} }
@ -876,7 +882,9 @@ public class ConfigurationImpl
ConfigurationImpl clone = (ConfigurationImpl) cons.newInstance ConfigurationImpl clone = (ConfigurationImpl) cons.newInstance
(new Object[]{ Boolean.FALSE }); (new Object[]{ Boolean.FALSE });
clone._globals = _globals; clone._globals = _globals;
clone.fromProperties(toProperties(true)); Map map = new HashMap(toProperties(true));
clone.fromProperties(map);
clone._fullProps = map;
return clone; return clone;
} catch (RuntimeException re) { } catch (RuntimeException re) {
throw re; throw re;