org.datanucleus.AbstractNucleusContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datanucleus-core Show documentation
Show all versions of datanucleus-core Show documentation
DataNucleus Core provides the primary components of a heterogenous Java persistence solution.
It supports persistence API's being layered on top of the core functionality.
/**********************************************************************
Copyright (c) 2014 Andy Jefferson and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Contributors:
...
**********************************************************************/
package org.datanucleus;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.datanucleus.api.ApiAdapter;
import org.datanucleus.api.ApiAdapterFactory;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.exceptions.NucleusUserException;
import org.datanucleus.metadata.MetaDataListener;
import org.datanucleus.metadata.MetaDataManager;
import org.datanucleus.plugin.PluginManager;
import org.datanucleus.properties.CorePropertyValidator;
import org.datanucleus.store.types.TypeManager;
import org.datanucleus.store.types.TypeManagerImpl;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;
import org.datanucleus.util.StringUtils;
/**
* Base implementation of a NucleusContext, providing configuration, metadata management, type management, plugin management and ClassLoader services.
*/
public abstract class AbstractNucleusContext implements NucleusContext
{
/** Configuration for this context. */
protected final Configuration config;
/** Manager for plug-ins. */
protected final PluginManager pluginManager;
/** MetaDataManager for handling the MetaData. */
protected MetaDataManager metaDataManager = null;
/** API adapter used by the context. **/
protected final ApiAdapter apiAdapter;
/** Manager for java types. */
protected TypeManager typeManager;
/** Name of the class providing the ClassLoaderResolver. */
protected final String classLoaderResolverClassName;
/** Map of the ClassLoaderResolver, keyed by the clr class and the primaryLoader name. */
protected transient Map classLoaderResolverMap = new ConcurrentHashMap<>();
/** Default ClassLoaderResolver, when no primaryLoader is specified. */
protected ClassLoaderResolver defaultCLR = null;
public static final Set STARTUP_PROPERTIES = new HashSet<>();
static
{
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_PLUGIN_REGISTRY_CLASSNAME);
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_PLUGIN_REGISTRYBUNDLECHECK);
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_PLUGIN_ALLOW_USER_BUNDLES);
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_PLUGIN_VALIDATEPLUGINS);
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_CLASSLOADER_RESOLVER_NAME);
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_PERSISTENCE_XML_FILENAME);
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_CLASSLOADER_PRIMARY);
STARTUP_PROPERTIES.add(PropertyNames.PROPERTY_METADATA_LISTENER_OBJECT);
}
public AbstractNucleusContext(String apiName, Map startupProps, PluginManager pluginMgr)
{
this.pluginManager = (pluginMgr != null) ? pluginMgr : PluginManager.createPluginManager(startupProps, this.getClass().getClassLoader());
// Create Configuration (with defaults for plugins), and impose any startup properties
this.config = new Configuration(this);
if (startupProps != null && !startupProps.isEmpty())
{
this.config.setPersistenceProperties(startupProps);
}
// Set the name of class loader resolver
String clrName = config.getStringProperty(PropertyNames.PROPERTY_CLASSLOADER_RESOLVER_NAME);
if ("datanucleus".equalsIgnoreCase(clrName))
{
classLoaderResolverClassName = ClassLoaderResolverImpl.class.getName();
}
else
{
// Fallback to the plugin mechanism
if (clrName != null)
{
classLoaderResolverClassName = pluginManager.getAttributeValueForExtension("org.datanucleus.classloader_resolver", "name", clrName, "class-name");
if (classLoaderResolverClassName == null)
{
// User has specified a classloader_resolver plugin that has not registered
throw new NucleusUserException(Localiser.msg("001001", clrName)).setFatal();
}
}
else
{
classLoaderResolverClassName = null;
}
}
// Initialise API, and set defaults for properties for the API
if (apiName != null)
{
this.apiAdapter = ApiAdapterFactory.getInstance().getApiAdapter(apiName, pluginManager);
this.config.setDefaultProperties(apiAdapter.getDefaultFactoryProperties());
}
else
{
this.apiAdapter = null;
}
}
@Override
public void applyDefaultProperties(Configuration conf)
{
conf.addDefaultProperty(PropertyNames.PROPERTY_PLUGIN_REGISTRY_CLASSNAME, null, null, null, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_PLUGIN_ALLOW_USER_BUNDLES, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_PLUGIN_VALIDATEPLUGINS, null, false, false, false);
conf.addDefaultProperty(PropertyNames.PROPERTY_PLUGIN_REGISTRYBUNDLECHECK, null, "EXCEPTION", CorePropertyValidator.class.getName(), false, false);
conf.addDefaultProperty(PropertyNames.PROPERTY_CLASSLOADER_RESOLVER_NAME, null, null, null, false, false);
conf.addDefaultProperty(PropertyNames.PROPERTY_CLASSLOADER_PRIMARY, null, null, null, false, false);
// MetaData
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_IGNORE_METADATA_FOR_MISSING_CLASSES, null, false, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_ALWAYS_DETACHABLE, null, false, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_XML_VALIDATE, null, false, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_XML_NAMESPACE_AWARE, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_AUTOREGISTER, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_ALLOW_XML, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_ALLOW_ANNOTATIONS, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_DEFAULT_NULLABLE, null, true, true, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_ALLOW_LOAD_AT_RUNTIME, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_SUPPORT_ORM, null, null, false, false);
conf.addDefaultProperty(PropertyNames.PROPERTY_METADATA_JDO_SUFFIX, null, "jdo", null, false, false);
conf.addDefaultProperty(PropertyNames.PROPERTY_METADATA_ORM_SUFFIX, null, "orm", null, false, false);
conf.addDefaultProperty(PropertyNames.PROPERTY_METADATA_JDOQUERY_SUFFIX, null, "jdoquery", null, false, false);
conf.addDefaultProperty(PropertyNames.PROPERTY_METADATA_DEFAULT_INHERITANCE_STRATEGY, null, "JDO2", CorePropertyValidator.class.getName(), false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_EMBEDDED_PC_FLAT, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_USE_DISCRIMINATOR_FOR_SINGLE_TABLE, null, false, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_USE_DISCRIMINATOR_DEFAULT_CLASS_NAME, null, true, false, false);
conf.addDefaultBooleanProperty(PropertyNames.PROPERTY_METADATA_JAVAX_VALIDATION_SHORTCUTS, null, false, false, false);
}
@Override
public synchronized void initialise()
{
logConfiguration();
}
@Override
public void close()
{
if (typeManager != null)
{
typeManager.close();
}
}
@Override
public ApiAdapter getApiAdapter()
{
return apiAdapter;
}
@Override
public String getApiName()
{
return apiAdapter != null ? apiAdapter.getName() : null;
}
@Override
public Configuration getConfiguration()
{
return config;
}
@Override
public PluginManager getPluginManager()
{
return pluginManager;
}
@Override
public synchronized MetaDataManager getMetaDataManager()
{
if (metaDataManager == null)
{
String apiName = getApiName();
try
{
metaDataManager = (MetaDataManager)pluginManager.createExecutableExtension("org.datanucleus.metadata_manager", new String[]{"name"}, new String[]{apiName},
"class", new Class[] {ClassConstants.NUCLEUS_CONTEXT}, new Object[]{this});
if (metaDataManager != null && config.hasProperty(PropertyNames.PROPERTY_METADATA_LISTENER_OBJECT))
{
MetaDataListener mdl = (MetaDataListener)config.getProperty(PropertyNames.PROPERTY_METADATA_LISTENER_OBJECT);
metaDataManager.registerListener(mdl);
}
}
catch (Exception e)
{
throw new NucleusException(Localiser.msg("008010", apiName, e.getMessage()), e);
}
if (metaDataManager == null)
{
throw new NucleusException(Localiser.msg("008009", apiName));
}
}
return metaDataManager;
}
@Override
public boolean supportsORMMetaData()
{
return true;
}
@Override
public TypeManager getTypeManager()
{
if (typeManager == null)
{
this.typeManager = new TypeManagerImpl(this);
}
return typeManager;
}
@Override
public ClassLoaderResolver getClassLoaderResolver(ClassLoader primaryLoader)
{
if (primaryLoader == null && defaultCLR != null)
{
return defaultCLR;
}
// Set the key we will refer to this loader by
String resolverName = config.getStringProperty(PropertyNames.PROPERTY_CLASSLOADER_RESOLVER_NAME);
String key = resolverName!=null ? resolverName : "datanucleus";
if (primaryLoader != null)
{
key += ":[" + StringUtils.toJVMIDString(primaryLoader) + "]";
}
ClassLoaderResolver clr = null;
if (classLoaderResolverMap != null)
{
clr = classLoaderResolverMap.get(key);
if (clr != null)
{
// Return the cached loader resolver
return clr;
}
}
else
{
classLoaderResolverMap = new ConcurrentHashMap();
}
// Create the ClassLoaderResolver of the required type with this primary loader
if (resolverName == null)
{
// Use built-in ClassLoaderResolver
clr = new ClassLoaderResolverImpl(primaryLoader);
}
else
{
// User-type ClassLoaderResolver
try
{
clr = (ClassLoaderResolver)pluginManager.createExecutableExtension("org.datanucleus.classloader_resolver", "name", resolverName,
"class-name", new Class[] {ClassLoader.class}, new Object[] {primaryLoader});
}
catch (ClassNotFoundException cnfe)
{
throw new NucleusUserException(Localiser.msg("001002", classLoaderResolverClassName), cnfe).setFatal();
}
catch (Exception e)
{
throw new NucleusUserException(Localiser.msg("001003", classLoaderResolverClassName), e).setFatal();
}
}
// Add user ClassLoader if defined
ClassLoader userCL = (ClassLoader)config.getProperty(PropertyNames.PROPERTY_CLASSLOADER_PRIMARY);
if (userCL != null)
{
clr.registerUserClassLoader(userCL);
}
if (primaryLoader == null && primaryLoader == null)
{
defaultCLR = clr;
}
else
{
classLoaderResolverMap.put(key, clr);
}
return clr;
}
/**
* Method to log the configuration of this context.
*/
protected void logConfiguration()
{
if (NucleusLogger.PERSISTENCE.isDebugEnabled())
{
NucleusLogger.PERSISTENCE.debug("================= NucleusContext ===============");
String javaVersion = System.getProperty("java.version");
if (StringUtils.isWhitespace(javaVersion))
{
javaVersion = "unknown";
}
NucleusLogger.PERSISTENCE.debug(Localiser.msg("008000", pluginManager.getVersionForBundle("org.datanucleus"), javaVersion, System.getProperty("os.name")));
NucleusLogger.PERSISTENCE.debug("Persistence API : " + getApiName());
if (config.hasPropertyNotNull(PropertyNames.PROPERTY_PERSISTENCE_UNIT_NAME))
{
NucleusLogger.PERSISTENCE.debug("Persistence-Unit : " + config.getStringProperty(PropertyNames.PROPERTY_PERSISTENCE_UNIT_NAME));
}
NucleusLogger.PERSISTENCE.debug("Plugin Registry : " + pluginManager.getRegistryClassName());
Object primCL = config.getProperty(PropertyNames.PROPERTY_CLASSLOADER_PRIMARY);
String clrName = config.getStringProperty(PropertyNames.PROPERTY_CLASSLOADER_RESOLVER_NAME);
if (clrName == null)
{
clrName = "default";
}
NucleusLogger.PERSISTENCE.debug("ClassLoading : " + clrName + (primCL != null ? ("primary=" + primCL) : ""));
logConfigurationDetails();
NucleusLogger.PERSISTENCE.debug("================================================");
}
}
/**
* Convenience method so that extending implementations can log their own configuration.
*/
protected abstract void logConfigurationDetails();
}