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 b3317a508..b256916ff 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
@@ -99,6 +99,41 @@ public class Configurations {
return clsName + "(" + props + ")";
}
+ /**
+ * Return a plugin string that combines the properties of the given plugin
+ * strings, where properties of override
will override the
+ * same properties of orig
.
+ */
+ public static String combinePlugins(String orig, String override) {
+ if (StringUtils.isEmpty(orig))
+ return override;
+ if (StringUtils.isEmpty(override))
+ return orig;
+
+ String origCls = getClassName(orig);
+ String overrideCls = getClassName(override);
+ String cls;
+ if (StringUtils.isEmpty(origCls))
+ cls = overrideCls;
+ else if (StringUtils.isEmpty(overrideCls))
+ cls = origCls;
+ else if (!origCls.equals(overrideCls))
+ return override; // completely different plugin
+ else
+ cls = origCls;
+
+ String origProps = getProperties(orig);
+ String overrideProps = getProperties(override);
+ if (StringUtils.isEmpty(origProps))
+ return getPlugin(cls, overrideProps);
+ if (StringUtils.isEmpty(overrideProps))
+ return getPlugin(cls, origProps);
+
+ Properties props = parseProperties(origProps);
+ props.putAll(parseProperties(overrideProps));
+ return getPlugin(cls, serializeProperties(props));
+ }
+
/**
* Create the instance with the given class name, using the given
* class loader. No configuration of the instance is performed by
diff --git a/openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurations.java b/openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurations.java
index 43bd0e718..f67b40928 100644
--- a/openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurations.java
+++ b/openjpa-lib/src/test/java/org/apache/openjpa/lib/conf/TestConfigurations.java
@@ -12,6 +12,9 @@
*/
package org.apache.openjpa.lib.conf;
+import java.util.HashMap;
+import java.util.Map;
+
import org.apache.openjpa.lib.test.AbstractTestCase;
import org.apache.openjpa.lib.util.Options;
@@ -77,6 +80,62 @@ public class TestConfigurations extends AbstractTestCase {
assertEquals("baz baz", opts.getProperty("biz"));
}
+ public void testCombinePlugins() {
+ assertPluginsCombined("jpa", null,
+ null, null,
+ "jpa", null);
+ assertPluginsCombined("jpa", null,
+ "jpa", null,
+ "jpa", null);
+ assertPluginsCombined("jdo", null,
+ "jpa", null,
+ "jpa", null);
+ assertPluginsCombined("jdo", new String[] { "foo", "bar" },
+ "jpa", null,
+ "jpa", null);
+ assertPluginsCombined("jdo", new String[] { "foo", "bar" },
+ "jpa", new String[] { "biz", "baz" },
+ "jpa", new String[] { "biz", "baz" });
+ assertPluginsCombined("jdo", new String[] { "foo", "bar" },
+ null, new String[] { "biz", "baz" },
+ "jdo", new String[] { "foo", "bar", "biz", "baz" });
+ assertPluginsCombined(null, new String[] { "foo", "bar" },
+ null, new String[] { "biz", "baz" },
+ null, new String[] { "foo", "bar", "biz", "baz" });
+ assertPluginsCombined(null, new String[] { "foo", "bar" },
+ "jpa", new String[] { "biz", "baz" },
+ "jpa", new String[] { "foo", "bar", "biz", "baz" });
+ assertPluginsCombined("jpa", new String[] { "foo", "bar" },
+ "jpa", new String[] { "biz", "baz" },
+ "jpa", new String[] { "foo", "bar", "biz", "baz" });
+ assertPluginsCombined("jpa", new String[] { "foo", "bar" },
+ "jpa", new String[] { "foo", "baz" },
+ "jpa", new String[] { "foo", "baz" });
+ }
+
+ private void assertPluginsCombined(String cls1, String[] props1,
+ String cls2, String[] props2, String expCls, String[] expProps) {
+ String plugin1 = Configurations.getPlugin(cls1,
+ Configurations.serializeProperties(toProperties(props1)));
+ String plugin2 = Configurations.getPlugin(cls2,
+ Configurations.serializeProperties(toProperties(props2)));
+
+ String res = Configurations.combinePlugins(plugin1, plugin2);
+ String resCls = Configurations.getClassName(res);
+ Map resProps = Configurations.parseProperties(Configurations.
+ getProperties(res));
+ assertEquals(expCls, resCls);
+ assertEquals(toProperties(expProps), resProps);
+ }
+
+ private static Map toProperties(String[] props) {
+ Map map = new HashMap();
+ if (props != null)
+ for (int i = 0; i < props.length; i++)
+ map.put(props[i], props[++i]);
+ return map;
+ }
+
public static void main(String[] args) {
main(TestConfigurations.class);
}
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java
index 04d19de3d..ec67d85a2 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceProductDerivation.java
@@ -32,10 +32,11 @@ import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.conf.OpenJPAProductDerivation;
import org.apache.openjpa.lib.conf.AbstractProductDerivation;
-import org.apache.openjpa.lib.conf.ProductDerivations;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationProvider;
+import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.conf.MapConfigurationProvider;
+import org.apache.openjpa.lib.conf.ProductDerivations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.meta.XMLMetaDataParser;
import org.apache.openjpa.lib.util.Localizer;
@@ -382,10 +383,27 @@ public class PersistenceProductDerivation
@Override
public void setInto(Configuration conf) {
- if (conf instanceof OpenJPAConfiguration)
- ((OpenJPAConfiguration) conf).setSpecification(SPEC_JPA);
- super.setInto(conf, null);
+ if (conf instanceof OpenJPAConfiguration) {
+ OpenJPAConfiguration oconf = (OpenJPAConfiguration) conf;
+ oconf.setSpecification(SPEC_JPA);
+ // we merge several persistence.xml elements into the
+ // MetaDataFactory property implicitly. if the user has a
+ // global openjpa.xml with this property set, its value will
+ // get overwritten by our implicit setting. so instead, combine
+ // the global value with our settings
+ String orig = oconf.getMetaDataFactory();
+ if (!StringUtils.isEmpty(orig)) {
+ String key = ProductDerivations.getConfigurationKey
+ ("MetaDataFactory", getProperties());
+ Object override = getProperties().get(key);
+ if (override instanceof String)
+ addProperty(key, Configurations.combinePlugins(orig,
+ (String) override));
+ }
+ }
+
+ super.setInto(conf, null);
Log log = conf.getConfigurationLog();
if (log.isTraceEnabled()) {
String src = (_source == null) ? "?" : _source;
diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java
index 901eb01e8..5352a18a5 100644
--- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java
+++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PersistenceUnitInfoImpl.java
@@ -33,6 +33,7 @@ import javax.sql.DataSource;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.conf.ProductDerivations;
import org.apache.openjpa.lib.meta.SourceTracker;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.MultiClassLoader;
@@ -404,20 +405,14 @@ public class PersistenceUnitInfoImpl
}
metaFactoryProps.put("Resources", rsrcs.toString());
}
+
+ // set persistent class locations as properties of metadata factory,
+ // combining them with any existing metadata factory props
if (!metaFactoryProps.isEmpty()) {
- // set persistent class locations as properties of metadata factory
- String factory = (String) Configurations.getProperty
+ String key = ProductDerivations.getConfigurationKey
("MetaDataFactory", map);
- if (factory == null)
- factory = Configurations.serializeProperties(metaFactoryProps);
- else {
- String clsName = Configurations.getClassName(factory);
- metaFactoryProps.putAll(Configurations.parseProperties
- (Configurations.getProperties(factory)));
- factory = Configurations.getPlugin(clsName,
- Configurations.serializeProperties(metaFactoryProps));
- }
- map.put("openjpa.MetaDataFactory", factory);
+ map.put(key, Configurations.combinePlugins((String) map.get(key),
+ Configurations.serializeProperties(metaFactoryProps)));
}
// always record provider name for product derivations to access