Allow our JPA ConfigurationProviderImpl to find a default persistence unit in

persistence.xml when no explicit configuration is given to dev tools.  Do this
in a backwards-compatible way that won't break previous behavior or other facade
behavior (JDO).  This means you should no longer have to pass 
"-p persistence.xml" to tools like the enhancer, nor should you have to specify
a properties argument to the PCEnhancerAgent in the premain for runtime 
enhancement.



git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@430897 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2006-08-11 21:07:58 +00:00
parent 07a13ab908
commit aba057d644
19 changed files with 293 additions and 144 deletions

View File

@ -22,7 +22,7 @@ import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
import org.apache.openjpa.jdbc.meta.MappingTool;
import org.apache.openjpa.jdbc.schema.SchemaTool;
import org.apache.openjpa.lib.ant.AbstractTask;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationImpl;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.MultiLoaderClassResolver;
@ -161,7 +161,7 @@ public class MappingToolTask
flags.meta = meta;
}
protected Configuration newConfiguration() {
protected ConfigurationImpl newConfiguration() {
return new JDBCConfigurationImpl();
}

View File

@ -26,7 +26,7 @@ import org.apache.openjpa.jdbc.meta.PropertiesReverseCustomizer;
import org.apache.openjpa.jdbc.meta.ReverseCustomizer;
import org.apache.openjpa.jdbc.meta.ReverseMappingTool;
import org.apache.openjpa.lib.ant.AbstractTask;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationImpl;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.util.CodeFormat;
import org.apache.openjpa.lib.util.Files;
@ -215,7 +215,7 @@ public class ReverseMappingToolTask
return flags.format;
}
protected Configuration newConfiguration() {
protected ConfigurationImpl newConfiguration() {
return new JDBCConfigurationImpl();
}

View File

@ -21,7 +21,7 @@ import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.conf.JDBCConfigurationImpl;
import org.apache.openjpa.jdbc.schema.SchemaTool;
import org.apache.openjpa.lib.ant.AbstractTask;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationImpl;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.lib.util.Localizer;
@ -121,7 +121,7 @@ public class SchemaToolTask
this.file = file;
}
protected Configuration newConfiguration() {
protected ConfigurationImpl newConfiguration() {
return new JDBCConfigurationImpl();
}

View File

@ -93,20 +93,19 @@ public class JDBCConfigurationImpl
/**
* Constructor.
*
* @param loadDefaults whether to attempt to load the default
* <code>org.apache.openjpa.properties</code> resource
* @param loadGlobals whether to attempt to load the global properties
*/
public JDBCConfigurationImpl(boolean loadDefaults) {
this(true, loadDefaults);
public JDBCConfigurationImpl(boolean loadGlobals) {
this(true, loadGlobals);
}
/**
* Constructor.
*
* @param derivations whether to apply product derivations
* @param loadDefaults whether to attempt to load the default properties
* @param loadGlobals whether to attempt to load the global properties
*/
public JDBCConfigurationImpl(boolean derivations, boolean loadDefaults) {
public JDBCConfigurationImpl(boolean derivations, boolean loadGlobals) {
super(false, false);
String[] aliases;
@ -297,14 +296,10 @@ public class JDBCConfigurationImpl
// a bug in JRun, and we can get around it by forcing
// Instruction.class to be loaded and initialized
// before TypedInstruction.class
try {
serp.bytecode.lowlevel.Entry.class.getName();
} catch (Throwable t) {
}
try {
serp.bytecode.Instruction.class.getName();
} catch (Throwable t) {
}
try { serp.bytecode.lowlevel.Entry.class.getName(); }
catch (Throwable t) {}
try { serp.bytecode.Instruction.class.getName(); }
catch (Throwable t) {}
supportedOptions().add(OPTION_QUERY_SQL);
supportedOptions().add(OPTION_JDBC_CONNECTION);
@ -313,8 +308,8 @@ public class JDBCConfigurationImpl
if (derivations)
ProductDerivations.beforeConfigurationLoad(this);
if (loadDefaults)
loadDefaults();
if (loadGlobals)
loadGlobals();
}
/**

View File

@ -23,7 +23,7 @@ import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.lib.ant.AbstractTask;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationImpl;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.MetaDataTool;
@ -58,7 +58,7 @@ public class MetaDataToolTask
this.fileName = fileName;
}
protected Configuration newConfiguration() {
protected ConfigurationImpl newConfiguration() {
return new OpenJPAConfigurationImpl();
}

View File

@ -21,7 +21,7 @@ import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.conf.OpenJPAConfigurationImpl;
import org.apache.openjpa.enhance.PCEnhancer;
import org.apache.openjpa.lib.ant.AbstractTask;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationImpl;
import org.apache.openjpa.lib.util.Files;
import org.apache.openjpa.meta.MetaDataRepository;
@ -73,7 +73,7 @@ public class PCEnhancerTask
flags.tmpClassLoader = tmpClassLoader;
}
protected Configuration newConfiguration() {
protected ConfigurationImpl newConfiguration() {
return new OpenJPAConfigurationImpl();
}

View File

@ -58,10 +58,6 @@ import org.apache.openjpa.util.StoreFacadeTypeRegistry;
/**
* Implementation of the {@link OpenJPAConfiguration} interface.
* On construction, the class will attempt to locate a default properties
* file called <code>openjpa.properties</code> located at any top level token
* of the CLASSPATH. See the {@link ConfigurationImpl} class description
* for details.
*
* @see ConfigurationImpl
* @author Marc Prud'hommeaux
@ -149,7 +145,7 @@ public class OpenJPAConfigurationImpl
new StoreFacadeTypeRegistry();
/**
* Default constructor. Attempts to load default properties.
* Default constructor. Attempts to load global properties.
*/
public OpenJPAConfigurationImpl() {
this(true);
@ -158,21 +154,19 @@ public class OpenJPAConfigurationImpl
/**
* Constructor.
*
* @param loadDefaults whether to attempt to load the default
* <code>openjpa.properties</code> resource
* @param loadGlobals whether to attempt to load the global properties
*/
public OpenJPAConfigurationImpl(boolean loadDefaults) {
this(true, loadDefaults);
public OpenJPAConfigurationImpl(boolean loadGlobals) {
this(true, loadGlobals);
}
/**
* Constructor.
*
* @param derivations whether to apply product derivations
* @param loadDefaults whether to attempt to load the default
* <code>openjpa.properties</code> resource
* @param loadGlobals whether to attempt to load the global properties
*/
public OpenJPAConfigurationImpl(boolean derivations, boolean loadDefaults) {
public OpenJPAConfigurationImpl(boolean derivations, boolean loadGlobals) {
super(false);
String[] aliases;
@ -514,8 +508,8 @@ public class OpenJPAConfigurationImpl
if (derivations)
ProductDerivations.beforeConfigurationLoad(this);
if (loadDefaults)
loadDefaults();
if (loadGlobals)
loadGlobals();
}
public Collection supportedOptions() {

View File

@ -27,6 +27,9 @@ import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.ConfigurationImpl;
import org.apache.openjpa.lib.conf.ConfigurationProvider;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.util.Localizer;
/**
@ -55,7 +58,7 @@ public abstract class AbstractTask extends MatchingTask {
protected boolean useParent = false;
protected boolean isolate = false;
private Configuration _conf = null;
private ConfigurationImpl _conf = null;
private AntClassLoader _cl = null;
/**
@ -94,7 +97,7 @@ public abstract class AbstractTask extends MatchingTask {
* Implement this method to return a configuration object for the
* product in use.
*/
protected abstract Configuration newConfiguration();
protected abstract ConfigurationImpl newConfiguration();
/**
* Perform the task action on the given files.
@ -148,6 +151,16 @@ public abstract class AbstractTask extends MatchingTask {
}
public void execute() throws BuildException {
// if the user didn't supply a conf file, load the default
if (_conf == null)
_conf = newConfiguration();
if (_conf.getPropertiesResource() == null) {
ConfigurationProvider cp = Configurations.
loadDefaults(getClassLoader());
if (cp != null)
cp.setInto(_conf);
}
String[] files = getFiles();
try {
executeOn(files);
@ -156,8 +169,7 @@ public abstract class AbstractTask extends MatchingTask {
if (haltOnError)
throw new BuildException(e);
} finally {
if (_conf != null)
_conf.close();
_conf.close();
_conf = null;
}
}

View File

@ -105,7 +105,8 @@ public class ConfigurationImpl
private String _product = null;
private boolean _readOnly = false;
private Map _props = null;
private boolean _defaults = false;
private boolean _globals = false;
private String _auto = null;
private final List _vals = new ArrayList();
private List _prefixes = new ArrayList(2);
@ -127,9 +128,9 @@ public class ConfigurationImpl
/**
* Constructor.
*
* @param loadDefaults whether to attempt to load the default properties
* @param loadGlobals whether to attempt to load the global properties
*/
public ConfigurationImpl(boolean loadDefaults) {
public ConfigurationImpl(boolean loadGlobals) {
setProductName("openjpa"); // also adds as prop prefix
logFactoryPlugin = addPlugin("Log", true);
@ -145,28 +146,28 @@ public class ConfigurationImpl
logFactoryPlugin.setString(aliases[0]);
logFactoryPlugin.setInstantiatingGetter("getLogFactory");
if (loadDefaults)
loadDefaults();
if (loadGlobals)
loadGlobals();
}
/**
* Automatically load default values from the system's
* Automatically load global values from the system's
* {@link ConfigurationProvider}s, and from System properties.
*/
public boolean loadDefaults() {
ConfigurationProvider provider = Configurations.loadDefaults
public boolean loadGlobals() {
ConfigurationProvider provider = Configurations.loadGlobals
(getClass().getClassLoader());
if (provider != null)
provider.setInto(this);
// let system properties override other defaults
// let system properties override other globals
try {
fromProperties(new HashMap(System.getProperties()));
} catch (SecurityException se) {
// security manager might disallow
}
_defaults = true;
_globals = true;
if (provider == null) {
Log log = getConfigurationLog();
if (log.isTraceEnabled())
@ -575,9 +576,9 @@ public class ConfigurationImpl
// this way we preserve the original formatting of the user's props
// instead of the defaults. this is important for caching on
// configuration objects
if (_defaults) {
if (_globals) {
_props = null;
_defaults = false;
_globals = false;
}
Map remaining = new HashMap(map);
@ -732,6 +733,10 @@ public class ConfigurationImpl
return false;
}
//////////////////////
// Auto-configuration
//////////////////////
/**
* This method loads the named resource as a properties file. It is
* useful for auto-configuration tools so users can specify a
@ -740,6 +745,7 @@ public class ConfigurationImpl
public void setProperties(String resourceName) throws IOException {
Configurations.load(resourceName, getClass().getClassLoader()).
setInto(this);
_auto = resourceName;
}
/**
@ -749,6 +755,15 @@ public class ConfigurationImpl
*/
public void setPropertiesFile(File file) throws IOException {
Configurations.load(file, getClass().getClassLoader()).setInto(this);
_auto = file.toString();
}
/**
* Return the resource that was set via auto-configuration methods
* {@link #setProperties} or {@link #setPropertiesFile}, or null if none.
*/
public String getPropertiesResource() {
return _auto;
}
/////////////
@ -839,7 +854,7 @@ public class ConfigurationImpl
throws IOException, ClassNotFoundException {
fromProperties((Map) in.readObject());
_prefixes = (List) in.readObject();
_defaults = in.readBoolean();
_globals = in.readBoolean();
}
/**
@ -852,7 +867,7 @@ public class ConfigurationImpl
else
out.writeObject(toProperties(false));
out.writeObject(_prefixes);
out.writeBoolean(_defaults);
out.writeBoolean(_globals);
}
/**
@ -867,7 +882,7 @@ public class ConfigurationImpl
(new Object[]{ Boolean.FALSE });
clone._prefixes.clear();
clone._prefixes.addAll(_prefixes);
clone._defaults = _defaults;
clone._globals = _globals;
clone.fromProperties(toProperties(true));
return clone;
} catch (RuntimeException re) {

View File

@ -29,6 +29,11 @@ import java.util.Map;
*/
public interface ConfigurationProvider {
/**
* Load globals, or return false if no globals for this provider found.
*/
public boolean loadGlobals(ClassLoader loader) throws Exception;
/**
* Load defaults, or return false if no defaults for this provider found.
*/
@ -37,14 +42,20 @@ public interface ConfigurationProvider {
/**
* Load the given given resource, or return false if it is not a resource
* this provider understands. The given class loader may be null.
*
* @param anchor optional named anchor within a multiple-configuration
* resource
*/
public boolean load(String resource, ClassLoader loader) throws Exception;
public boolean load(String resource, String anchor, ClassLoader loader)
throws Exception;
/**
* Load given file, or return false if it is not a file this provider
* understands.
*
* @param anchor optional named anchor within a multiple-configuration file
*/
public boolean load(File file) throws Exception;
public boolean load(File file, String anchor) throws Exception;
/**
* Return properties loaded thus far, or empty map if none.

View File

@ -16,6 +16,7 @@
package org.apache.openjpa.lib.conf;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
@ -386,10 +387,8 @@ public class Configurations {
} else
buf.append(props[i]);
}
val = buf.toString();
}
opts.put(prop, val);
}
return opts;
@ -409,18 +408,35 @@ public class Configurations {
public static void populateConfiguration(Configuration conf, Options opts) {
String props = opts.removeProperty("properties", "p", null);
if (props != null && props.length() > 0) {
File file = new File(props);
String path = props;
String anchor = null;
int idx = path.lastIndexOf('#');
if (idx != -1) {
if (idx < path.length() - 1)
anchor = path.substring(idx + 1);
path = path.substring(0, idx);
if (path.length() == 0)
throw new MissingResourceException(_loc.get("anchor-only",
props).getMessage(), Configurations.class.getName(),
props);
}
File file = new File(path);
ConfigurationProvider provider;
if (file.isFile())
provider = load(file, null);
provider = load(file, anchor, null);
else {
file = new File("META-INF" + File.separatorChar + props);
file = new File("META-INF" + File.separatorChar + path);
if (file.isFile())
provider = load(file, null);
provider = load(file, anchor, null);
else
provider = load(props, null);
provider = load(path, anchor, null);
}
provider.setInto(conf);
} else {
ConfigurationProvider provider = loadDefaults(null);
if (provider != null)
provider.setInto(conf);
}
opts.setInto(conf);
}
@ -429,6 +445,21 @@ public class Configurations {
* Return a {@link ConfigurationProvider} that has parsed system defaults.
*/
public static ConfigurationProvider loadDefaults(ClassLoader loader) {
return load(loader, false);
}
/**
* Return a {@link ConfigurationProvider} that has parsed system globals.
*/
static ConfigurationProvider loadGlobals(ClassLoader loader) {
return load(loader, true);
}
/**
* Load globals or defaults.
*/
private static ConfigurationProvider load(ClassLoader loader,
boolean globals) {
if (loader == null)
loader = Thread.currentThread().getContextClassLoader();
Class[] impls = Services.getImplementorClasses
@ -443,7 +474,8 @@ public class Configurations {
providerCount++;
try {
if (provider.loadDefaults(loader))
if ((globals && provider.loadGlobals(loader))
|| (!globals && provider.loadDefaults(loader)))
return provider;
} catch (MissingResourceException mre) {
throw mre;
@ -455,13 +487,15 @@ public class Configurations {
errs.append(e.toString());
}
}
String type = (globals) ? "globals" : "defaults";
if (errs != null)
throw new MissingResourceException(errs.toString(),
Configurations.class.getName(), "defaults");
Configurations.class.getName(), type);
if (providerCount == 0)
throw new MissingResourceException(_loc.get ("no-providers",
ConfigurationProvider.class.getName()).getMessage(),
Configurations.class.getName(), "defaults");
Configurations.class.getName(), type);
return null;
}
@ -482,7 +516,32 @@ public class Configurations {
* resource. Throws {@link MissingResourceException} if resource does
* not exist.
*/
public static ConfigurationProvider load(String resource,
public static ConfigurationProvider load(String resource,
ClassLoader loader) {
if (resource == null || resource.length() == 0)
return null;
String path = resource;
String anchor = null;
int idx = path.indexOf('.');
if (idx != -1) {
if (idx < path.length() - 1)
anchor = path.substring(idx + 1);
path = path.substring(0, idx);
if (path.length() == 0)
throw new MissingResourceException(_loc.get("anchor-only",
resource).getMessage(), Configurations.class.getName(),
resource);
}
return load(path, anchor, loader);
}
/**
* Return a {@link ConfigurationProvider} that has parsed the given
* resource. Throws {@link MissingResourceException} if resource does
* not exist.
*/
public static ConfigurationProvider load(String resource, String anchor,
ClassLoader loader) {
if (resource == null || resource.length() == 0)
return null;
@ -501,7 +560,7 @@ public class Configurations {
providerCount++;
try {
if (provider.load(resource, loader))
if (provider.load(resource, anchor, loader))
return provider;
} catch (MissingResourceException mre) {
throw mre;
@ -534,6 +593,35 @@ public class Configurations {
if (file == null)
return null;
String anchor = null;
try {
String path = file.getCanonicalPath();
int idx = path.indexOf('.');
if (idx != -1) {
if (idx < path.length() - 1)
anchor = path.substring(idx + 1);
path = path.substring(0, idx);
if (path.length() == 0)
throw new MissingResourceException(_loc.get("anchor-only",
file).getMessage(), Configurations.class.getName(),
file.toString());
file = new File(path);
}
} catch (IOException ioe) {
// ignore
}
return load(file, anchor, loader);
}
/**
* Return a {@link ConfigurationProvider} that has parsed the given
* file. Throws {@link MissingResourceException} if file does not exist.
*/
public static ConfigurationProvider load(File file, String anchor,
ClassLoader loader) {
if (file == null)
return null;
if (loader == null)
loader = Thread.currentThread().getContextClassLoader();
Class[] impls = Services.getImplementorClasses
@ -543,7 +631,7 @@ public class Configurations {
for (int i = 0; i < impls.length; i++) {
provider = newProvider(impls[i]);
try {
if (provider != null && provider.load(file))
if (provider != null && provider.load(file, anchor))
return provider;
} catch (MissingResourceException mre) {
throw mre;
@ -576,10 +664,7 @@ public class Configurations {
_loc.get("naming-err", name).getMessage(), ne);
} finally {
if (ctx != null)
try {
ctx.close();
} catch (Exception e) {
}
try { ctx.close(); } catch (Exception e) {}
}
}
}

View File

@ -51,15 +51,20 @@ public class MapConfigurationProvider implements ConfigurationProvider {
addProperties(props);
}
public boolean loadGlobals(ClassLoader loader) throws Exception {
return false;
}
public boolean loadDefaults(ClassLoader loader) throws Exception {
return false;
}
public boolean load(String resource, ClassLoader loader) throws Exception {
public boolean load(String resource, String anchor, ClassLoader loader)
throws Exception {
return false;
}
public boolean load(File file) throws Exception {
public boolean load(File file, String anchor) throws Exception {
return false;
}

View File

@ -62,6 +62,8 @@ dup-with-different-prefixes: Found multiple properties with different valid \
prefixes. Properties: {0}, {1}.
plugin-creation-exception: An exception occurred while creating a plugin for \
value {0}. This exception will be consumed.
anchor-only: You cannot supply a configuration unit name only. You must also \
supply the name of the resource in which the unit appears.
Log-name: Log factory
Log-desc: LogFactory and configuration

View File

@ -21,11 +21,16 @@ public class ConfigurationTestConfigurationProvider
super(null);
}
public boolean loadDefaults(ClassLoader loader)
public boolean loadGlobals(ClassLoader loader)
throws IOException {
return load(null, loader);
}
public boolean loadDefaults(ClassLoader loader)
throws IOException {
return false;
}
public boolean load(String rsrc, ClassLoader loader)
throws IOException {
if (rsrc == null)

View File

@ -51,15 +51,15 @@ public class TestConfigurationImpl extends AbstractTestCase {
}
/**
* Test that default properties are found and loaded.
* Test that global properties are found and loaded.
*/
public void testDefaults() {
public void testGlobals() {
System.setProperty("openjpa.sysKey", "sysvalue");
assertNull(_conf.getTestKey());
assertNull(_conf.getSysKey());
assertNull(_conf.getPluginKey());
assertNull(_conf.getObjectKey());
assertTrue(_conf.loadDefaults());
assertTrue(_conf.loadGlobals());
assertEquals("testvalue", _conf.getTestKey());
assertEquals("sysvalue", _conf.getSysKey());
assertNull(_conf.getPluginKey());
@ -70,7 +70,7 @@ public class TestConfigurationImpl extends AbstractTestCase {
_conf.setSysKey(null);
System.setProperty("openjpatest.properties", "foo.properties");
try {
assertTrue(!_conf.loadDefaults());
assertTrue(!_conf.loadGlobals());
fail("Should have thrown exception for missing resource.");
} catch (MissingResourceException mre) {
}
@ -78,7 +78,7 @@ public class TestConfigurationImpl extends AbstractTestCase {
// set back for remainder of tests
System.setProperty("openjpatest.properties", "test.properties");
System.setProperty("openjpa.pluginKey", "java.lang.Object");
assertTrue(_conf.loadDefaults());
assertTrue(_conf.loadGlobals());
assertEquals("testvalue", _conf.getTestKey());
assertEquals("sysvalue", _conf.getSysKey());
assertEquals("java.lang.Object", _conf.getPluginKey());
@ -90,7 +90,7 @@ public class TestConfigurationImpl extends AbstractTestCase {
* Test that the configuration is serialized to properties correctly.
*/
public void testToProperties() {
assertTrue(_conf.loadDefaults());
assertTrue(_conf.loadGlobals());
assertEquals("testvalue", _conf.getTestKey());
Map props = _conf.toProperties(false);
assertEquals("testvalue", props.get("openjpa.testKey"));
@ -209,7 +209,7 @@ public class TestConfigurationImpl extends AbstractTestCase {
* Test serialization.
*/
public void testSerialization() throws Exception {
assertTrue(_conf.loadDefaults());
assertTrue(_conf.loadGlobals());
_conf.setTestKey("testvalue");
_conf.setSysKey("sysvalue");
_conf.setObjectKey(new Object());

View File

@ -71,7 +71,6 @@
refid="enhance.path.ref"
pathsep=" "/>
<java classname="org.apache.openjpa.enhance.PCEnhancer">
<arg line="-p persistence.xml"/>
<arg line="${enhance.files}"/>
<classpath>
<path refid="maven.dependency.classpath"/>

View File

@ -18,6 +18,7 @@ package org.apache.openjpa.persistence;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
@ -26,8 +27,7 @@ import java.util.MissingResourceException;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.MapConfigurationProvider;
@ -35,15 +35,21 @@ import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.meta.XMLMetaDataParser;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.GeneralException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
/**
* Configuration provider capable of loading a {@link Configuration} from
* the current environment's JPA-style XML configuration data.
*
* For defaults, looks in <code>openjpa.properties</code> system property for
* For globals, looks in <code>openjpa.properties</code> system property for
* the location of a file to parse. If no system property is defined, the
* default resource location of <code>openjpa.xml</code> is used.
* If it exists, the resource is parsed as an XML file.
* default resource location of <code>META-INF/openjpa.xml</code> is used.
*
* For defaults, looks for <code>META-INF/persistence.xml</code>.
* Within <code>persistence.xml</code>, look for the named persistence unit, or
* if no name given, an OpenJPA unit (preferring an unnamed OpenJPA unit to
* a named one).
*
* @nojavadoc
* @since 4.0.0
@ -51,8 +57,8 @@ import org.apache.openjpa.util.GeneralException;
public class ConfigurationProviderImpl
extends MapConfigurationProvider {
private static final String RSRC_DEFAULT = "openjpa.xml";
private static final String RSRC_SPEC = "META-INF/persistence.xml";
private static final String RSRC_GLOBAL = "META-INF/openjpa.xml";
private static final String RSRC_DEFAULT = "META-INF/persistence.xml";
private static final Localizer _loc = Localizer.forPackage
(ConfigurationProviderImpl.class);
@ -86,7 +92,7 @@ public class ConfigurationProviderImpl
if (pinfo == null)
return false;
String providerName = pinfo.getPersistenceProviderClassName();
if (providerName != null && providerName.length() != 0
if (!StringUtils.isEmpty(providerName)
&& !PersistenceProviderImpl.class.getName().equals(providerName))
return false;
@ -100,7 +106,6 @@ public class ConfigurationProviderImpl
if (impl.getPersistenceXmlFileUrl() != null)
_source = impl.getPersistenceXmlFileUrl().toString();
}
return true;
}
@ -109,12 +114,12 @@ public class ConfigurationProviderImpl
* overrides. If the resource is null, tries to load from persistence.xml,
* but still returns true if persistence.xml does not exist.
*/
public boolean load(String name, String rsrc, Map m)
public boolean load(String rsrc, String name, Map m)
throws IOException {
boolean explicit = rsrc != null && rsrc.length() > 0;
boolean explicit = !StringUtils.isEmpty(rsrc);
if (!explicit)
rsrc = RSRC_SPEC;
Boolean ret = load(name, rsrc, m, null, explicit);
rsrc = RSRC_DEFAULT;
Boolean ret = load(rsrc, name, m, null, explicit);
if (ret != null)
return ret.booleanValue();
if (explicit)
@ -127,30 +132,35 @@ public class ConfigurationProviderImpl
}
@Override
public boolean loadDefaults(ClassLoader loader)
public boolean loadGlobals(ClassLoader loader)
throws IOException {
String rsrc = System.getProperty("openjpa.properties");
String name = null;
boolean explicit = false;
if (rsrc == null)
rsrc = RSRC_DEFAULT;
else {
// separate name from <resrouce>:<name> string
explicit = true;
int idx = rsrc.lastIndexOf(':');
if (idx != -1) {
name = rsrc.substring(idx + 1);
rsrc = rsrc.substring(0, idx);
}
if (!rsrc.endsWith(".xml"))
return false;
boolean explicit = !StringUtils.isEmpty(rsrc);
String anchor = null;
int idx = (!explicit) ? -1 : rsrc.lastIndexOf('#');
if (idx != -1) {
// separate name from <resrouce>#<name> string
if (idx < rsrc.length() - 1)
anchor = rsrc.substring(idx + 1);
rsrc = rsrc.substring(0, idx);
}
return load(name, rsrc, null, loader, explicit) == Boolean.TRUE;
if (StringUtils.isEmpty(rsrc))
rsrc = RSRC_GLOBAL;
else if (!rsrc.endsWith(".xml"))
return false;
return load(rsrc, anchor, null, loader, explicit) == Boolean.TRUE;
}
@Override
public boolean loadDefaults(ClassLoader loader)
throws IOException {
return load(RSRC_DEFAULT, null, null, loader, false) == Boolean.TRUE;
}
/**
* Looks through the resources at <code>rsrc</code> for a configuration
* file that matches <code>name</code> (or the first one if
* file that matches <code>name</code> (or an unnamed one if
* <code>name</code> is <code>null</code>), and loads the XML in the
* resource into a new {@link PersistenceUnitInfo}. Then, applies the
* overrides in <code>m</code>.
@ -158,7 +168,7 @@ public class ConfigurationProviderImpl
* @return {@link Boolean#TRUE} if the resource was loaded, null if it
* does not exist, or {@link Boolean#FALSE} if it is not for OpenJPA
*/
private Boolean load(String name, String rsrc, Map m, ClassLoader loader,
private Boolean load(String rsrc, String name, Map m, ClassLoader loader,
boolean explicit)
throws IOException {
if (loader == null)
@ -187,52 +197,68 @@ public class ConfigurationProviderImpl
/**
* Parse resources at the given location. Searches for a
* PersistenceUnitInfo with the requested name, or the first
* one if no name is passed in.
* PersistenceUnitInfo with the requested name, or an OpenJPA unit if
* no name given (preferring an unnamed OpenJPA unit to a named one).
*/
private PersistenceUnitInfo parseResources(ConfigurationParser parser,
Enumeration<URL> urls, String name, ClassLoader loader)
throws IOException {
List<PersistenceUnitInfo> pinfos = new ArrayList<PersistenceUnitInfo>();
for (URL url : Collections.list(urls)) {
parser.parse(url);
List pinfos = parser.getResults();
for (PersistenceUnitInfo pinfo : (List<PersistenceUnitInfo>) pinfos)
{
if (name == null
|| name.equals(pinfo.getPersistenceUnitName()))
pinfos.addAll((List<PersistenceUnitInfo>) parser.getResults());
}
return findUnit(pinfos, name);
}
/**
* Find the unit with the given name, or an OpenJPA unit if no name is
* given (preferring an unnamed OpenJPA unit to a named one).
*/
private PersistenceUnitInfo findUnit(List<PersistenceUnitInfo> pinfos,
String name) {
PersistenceUnitInfo ojpa = null;
for (PersistenceUnitInfo pinfo : pinfos) {
// found named unit?
if (name != null) {
if (name.equals(pinfo.getPersistenceUnitName()))
return pinfo;
continue;
}
if (StringUtils.isEmpty(pinfo.getPersistenceProviderClassName())
|| PersistenceProviderImpl.class.getName().equals(pinfo.
getPersistenceProviderClassName())) {
// if no name given and found unnamed unit, return it.
// otherwise record as default unit unless we find a
// better match later
if (StringUtils.isEmpty(pinfo.getPersistenceUnitName()))
return pinfo;
if (ojpa == null)
ojpa = pinfo;
}
}
return null;
return ojpa;
}
@Override
public boolean load(String rsrc, ClassLoader loader)
public boolean load(String rsrc, String anchor, ClassLoader loader)
throws IOException {
String name = null;
int idx = rsrc.lastIndexOf(':');
if (idx != -1) {
name = rsrc.substring(idx + 1);
rsrc = rsrc.substring(0, idx);
}
if (!rsrc.endsWith(".xml"))
return false;
return load(name, rsrc, null, loader, true) == Boolean.TRUE;
return load(rsrc, anchor, null, loader, true) == Boolean.TRUE;
}
@Override
public boolean load(File file) {
public boolean load(File file, String anchor) {
if (!file.getName().endsWith(".xml"))
return false;
try {
ConfigurationParser parser = new ConfigurationParser(null);
parser.parse(file);
List pinfos = parser.getResults();
for (PersistenceUnitInfo pinfo : (List<PersistenceUnitInfo>) pinfos)
if (load(pinfo))
return true;
return false;
return load(findUnit((List<PersistenceUnitInfo>)
parser.getResults(), anchor));
} catch (IOException ioe) {
throw new GeneralException(ioe);
}

View File

@ -62,7 +62,7 @@ public class PersistenceProviderImpl
String resource, Map m) {
ConfigurationProviderImpl cp = new ConfigurationProviderImpl();
try {
if (cp.load(name, resource, m))
if (cp.load(resource, name, m))
return OpenJPAPersistence.toEntityManagerFactory(
Bootstrap.newBrokerFactory(cp, cp.getClassLoader()));
else

View File

@ -47,7 +47,7 @@ public class XMLConfiguration
lockManagerPlugin.setString("version");
ProductDerivations.beforeConfigurationLoad(this);
loadDefaults();
loadGlobals();
}
/**