org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2021 IBM Corporation. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
// 12/24/2012-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support
// 01/08/2013-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support
// 01/11/2013-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support
// 01/16/2013-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support
// 01/24/2013-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support
// 02/04/2013-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support
// 02/19/2013-2.5 Guy Pelletier
// - 389090: JPA 2.1 DDL Generation Support
// 05/06/2015-2.7 Tomas Kraus
// - Added partition isolation for persistence units.
package org.eclipse.persistence.internal.jpa;
import java.security.AccessController;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.TargetDatabase;
import org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl.TableCreationType;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetSystemProperty;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.tools.schemaframework.SchemaManager;
/**
* This is a helper/impl class for the EclipseLink EJB 3.0 provider
* The default constructor can be used to build the provider by reflection, after which it can
* be used to create EntityManagerFactories
*/
public class EntityManagerFactoryProvider {
public static final Map emSetupImpls = IsolatedHashMap.newMap();
// TEMPORARY - WILL BE REMOVED.
// Used to warn users about deprecated property name and suggest the valid name.
// TEMPORARY the old property names will be translated to the new ones and processed.
protected static final String oldPropertyNames[][] = {
{PersistenceUnitProperties.CONNECTION_POOL_MAX, "eclipselink.max-write-connections"},
{PersistenceUnitProperties.CONNECTION_POOL_MIN, "eclipselink.min-write-connections"},
{PersistenceUnitProperties.CONNECTION_POOL_MAX, "eclipselink.max-read-connections"},
{PersistenceUnitProperties.CONNECTION_POOL_MIN, "eclipselink.min-read-connections"},
{PersistenceUnitProperties.CONNECTION_POOL_MAX, "eclipselink.connections.max"},
{PersistenceUnitProperties.CONNECTION_POOL_MIN, "eclipselink.connections.min"},
{PersistenceUnitProperties.CONNECTION_POOL_INITIAL, "eclipselink.connections.initial"},
{PersistenceUnitProperties.CONNECTION_POOL_WAIT, "eclipselink.connections.wait"},
{PersistenceUnitProperties.CONNECTION_POOL_MAX, "eclipselink.write-connections.max"},
{PersistenceUnitProperties.CONNECTION_POOL_MIN, "eclipselink.write-connections.min"},
{PersistenceUnitProperties.CONNECTION_POOL_INITIAL, "eclipselink.write-connections.initial"},
{PersistenceUnitProperties.CONNECTION_POOL_MAX, "eclipselink.read-connections.max"},
{PersistenceUnitProperties.CONNECTION_POOL_MIN, "eclipselink.read-connections.min"},
{PersistenceUnitProperties.CONNECTION_POOL_SHARED, "eclipselink.read-connections.shared"},
{PersistenceUnitProperties.CONNECTION_POOL_INITIAL, "eclipselink.read-connections.initial"},
{PersistenceUnitProperties.JDBC_BIND_PARAMETERS, "eclipselink.bind-all-parameters"},
{PersistenceUnitProperties.TARGET_DATABASE, "eclipselink.platform.class.name"},
{PersistenceUnitProperties.TARGET_SERVER, "eclipselink.server.platform.class.name"},
{PersistenceUnitProperties.CACHE_SIZE_DEFAULT, "eclipselink.cache.default-size"},
{PersistenceUnitProperties.JDBC_USER , "eclipselink.jdbc.user"},
{PersistenceUnitProperties.JDBC_DRIVER ,"eclipselink.jdbc.driver"},
{PersistenceUnitProperties.JDBC_URL , "eclipselink.jdbc.url"},
{PersistenceUnitProperties.JDBC_PASSWORD , "eclipselink.jdbc.password"},
{PersistenceUnitProperties.WEAVING , "persistence.tools.weaving"},
{PersistenceUnitProperties.LOGGING_LEVEL + "." + SessionLog.METAMODEL, PersistenceUnitProperties.LOGGING_LEVEL + ".jpa_" + SessionLog.METAMODEL},
{PersistenceUnitProperties.LOGGING_LEVEL + "." + SessionLog.METADATA, PersistenceUnitProperties.LOGGING_LEVEL + ".ejb_or_" + SessionLog.METADATA}
};
/**
* Default constructor to allow reflection.
*/
public EntityManagerFactoryProvider() {
}
/**
* Add an EntityManagerSetupImpl to the cached list
* These are used to ensure all persistence units that are the same get the same underlying session
*/
public static void addEntityManagerSetupImpl(String name, EntityManagerSetupImpl setup){
synchronized (EntityManagerFactoryProvider.emSetupImpls) {
if (name == null){
EntityManagerFactoryProvider.emSetupImpls.put("", setup);
}
EntityManagerFactoryProvider.emSetupImpls.put(name, setup);
}
}
/**
* Calls the appropriate create,replace or alter SchemaManager api.
* @param ddlType - ddl operation to be performed
*/
protected static void generateDefaultTables(SchemaManager mgr, TableCreationType ddlType) {
if (ddlType == null || ddlType == TableCreationType.CREATE) {
mgr.createDefaultTables(true);
} else if (ddlType == TableCreationType.DROP) {
mgr.dropDefaultTables();
} else if (ddlType == TableCreationType.DROP_AND_CREATE) {
mgr.replaceDefaultTables(true, false, true);
} else if (ddlType == TableCreationType.EXTEND) {
mgr.extendDefaultTables(true);
}
}
/**
* Get configuration {@link System} property indicated by the specified {@code propertyKey}.
* Property value may be overridden by {@code overrides} {@link Map}.
* @param propertyKey The name of the configuration {@link System} property.
* @param overrides {@link Map} with property overrides.
* @return The {@link String} value of the property from {@code overrides} {@link Map} or value of configuration
* {@link System} property or {@code null} if property identified by {@code propertyKey} does not exist.
*/
public static String getConfigPropertyAsString(final String propertyKey, final Map overrides) {
final String value = overrides != null ? (String)overrides.get(propertyKey) : null;
return value != null ? value : PrivilegedAccessHelper.getSystemProperty(propertyKey);
}
/**
* Check the provided map for an object with the given key. If that object is not available, check the
* System properties. If it is not available from either location, return the default value.
*/
public static String getConfigPropertyAsString(String propertyKey, Map overrides, String defaultValue){
String value = getConfigPropertyAsString(propertyKey, overrides);
if (value == null){
value = defaultValue;
}
return value;
}
protected static String getConfigPropertyAsStringLogDebug(String propertyKey, Map overrides, AbstractSession session) {
return (String)getConfigPropertyLogDebug(propertyKey, overrides, session);
}
protected static String getConfigPropertyAsStringLogDebug(String propertyKey, Map overrides, AbstractSession session, boolean useSystemAsDefault) {
return (String)getConfigPropertyLogDebug(propertyKey, overrides, session, useSystemAsDefault);
}
protected static String getConfigPropertyAsStringLogDebug(String propertyKey, Map overrides, String defaultValue, AbstractSession session){
String value = getConfigPropertyAsStringLogDebug(propertyKey, overrides, session);
if (value == null){
value = defaultValue;
session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "property_value_default", new Object[]{propertyKey, value});
}
return value;
}
protected static Object getConfigPropertyLogDebug(String propertyKey, Map overrides, AbstractSession session){
return getConfigPropertyLogDebug(propertyKey, overrides, session, true);
}
protected static Object getConfigPropertyLogDebug(String propertyKey, Map overrides, AbstractSession session, boolean useSystemAsDefault){
Object value = null;
if (overrides != null){
value = overrides.get(propertyKey);
}
if ((value == null) && useSystemAsDefault){
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
value = AccessController.doPrivileged(new PrivilegedGetSystemProperty(propertyKey));
} else {
value = System.getProperty(propertyKey);
}
}
if ((value != null) && (session != null)) {
if (session.shouldLog(SessionLog.FINEST, SessionLog.PROPERTIES)) {
String overrideValue = PersistenceUnitProperties.getOverriddenLogStringForProperty(propertyKey);;
Object logValue = (overrideValue == null) ? value : overrideValue;
session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "property_value_specified", new Object[]{propertyKey, logValue});
}
}
return value;
}
public static boolean hasConfigProperty(String propertyKey, Map overrides) {
return getConfigProperty(propertyKey, overrides) != null;
}
protected static Object getConfigProperty(String propertyKey, Map overrides){
return getConfigProperty(propertyKey, overrides, true);
}
protected static Object getConfigProperty(String propertyKey, Map overrides, boolean useSystemAsDefault){
Object value = null;
if (overrides != null){
value = overrides.get(propertyKey);
}
if ((value == null) && useSystemAsDefault){
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
value = AccessController.doPrivileged(new PrivilegedGetSystemProperty(propertyKey));
} else {
value = System.getProperty(propertyKey);
}
}
return value;
}
protected static Object getConfigProperty(String propertyKey, Map overrides, Object defaultObj){
Object obj = getConfigProperty(propertyKey, overrides);
return (obj == null) ? defaultObj : obj;
}
/**
* Return the setup class for a given entity manager name
*/
public static EntityManagerSetupImpl getEntityManagerSetupImpl(String emName) {
synchronized (EntityManagerFactoryProvider.emSetupImpls){
if (emName == null){
return EntityManagerFactoryProvider.emSetupImpls.get("");
}
return EntityManagerFactoryProvider.emSetupImpls.get(emName);
}
}
public static Map getEmSetupImpls(){
return emSetupImpls;
}
/**
* Logs in to given session. If user has not specified TARGET_DATABASE
* the platform would be auto detected
* @param session The session to login to.
* @param properties User specified properties for the persistence unit
*/
protected static void login(DatabaseSessionImpl session, Map properties, boolean requiresConnection) {
String databaseGenerationAction = getConfigPropertyAsString(PersistenceUnitProperties.SCHEMA_GENERATION_DATABASE_ACTION, properties);
// Avoid an actual connection if we don't need one. If the user provides
// us with a user name and password we will connect. At minimum if they
// provide the platform we'll generate the DDL as if we had connected.
if ((databaseGenerationAction == null || databaseGenerationAction.equals(PersistenceUnitProperties.SCHEMA_GENERATION_NONE_ACTION)) && ! requiresConnection) {
session.setDatasourceAndInitialize();
} else {
String eclipselinkPlatform = (String)properties.get(PersistenceUnitProperties.TARGET_DATABASE);
if (eclipselinkPlatform == null || eclipselinkPlatform.equals(TargetDatabase.Auto) || session.isBroker()) {
// if user has not specified a database platform, try to detect.
// Will also look for jpa 2.1 schema properties.
session.loginAndDetectDatasource();
} else {
session.login();
}
}
}
/**
* Merge the properties from the source object into the target object. If the property
* exists in both objects, use the one from the target
* @return the target object
*/
public static Map mergeMaps(Map target, Map source){
Map map = new HashMap<>();
if (source != null){
map.putAll(source);
}
if (target != null){
map.putAll(target);
}
return map;
}
/**
* Copies source into target, removes from target all keysToBeRemoved.
* @return the target object
*/
public static Map removeSpecifiedProperties(Map source, Collection keysToBeRemoved){
Map target = new HashMap<>();
if (source != null){
target.putAll(source);
Iterator it = keysToBeRemoved.iterator();
while(it.hasNext()) {
target.remove(it.next());
}
}
return target;
}
/**
* target contains the entries from source with keysToBeKept.
* @return the target object
*/
public static Map keepSpecifiedProperties(Map source, Collection keysToBeKept){
Map target = new HashMap<>();
if (source != null){
target.putAll(source);
Iterator> it = source.entrySet().iterator();
while(it.hasNext()) {
Map.Entry entry = it.next();
if(keysToBeKept.contains(entry.getKey())) {
target.put(entry.getKey(), entry.getValue());
}
}
}
return target;
}
/**
* target is a array of two Maps
* the first one contains specified properties;
* the second all the rest.
* @return the target object
*/
public static Map[] splitSpecifiedProperties(Map source, Collection keysToBeKept){
HashMap in = new HashMap<>();
HashMap out = new HashMap<>();
Map[] target = new Map[]{in, out};
if (source != null){
Iterator> it = source.entrySet().iterator();
while(it.hasNext()) {
Map.Entry entry = it.next();
if(keysToBeKept.contains(entry.getKey())) {
in.put(entry.getKey(), entry.getValue());
} else {
out.put(entry.getKey(), entry.getValue());
}
}
}
return target;
}
/**
* Source Map is divided between Map[] in target.
* Target's i-th member contains all source's Map.Entries
* keys for which are in keys[i] Collection.
* Target's size equals keys' size + 1:
* all the source's Map.Entries not found in any of keys Collections
* go into the last target's map.
* @param keys is array of Maps of size n
* @return the target object is array of Maps of size n+1
*/
public static Map[] splitProperties(Map source, Collection[] keys){
@SuppressWarnings({"unchecked"})
Map[] target = (Map[]) new Map[keys.length + 1];
for (int i=0; i <= keys.length; i++) {
target[i] = new HashMap<>();
}
if (source != null){
Iterator> it = source.entrySet().iterator();
while(it.hasNext()) {
Map.Entry entry = it.next();
boolean isFound = false;
for (int i=0; i < keys.length && !isFound; i++) {
if (keys[i].contains(entry.getKey())) {
isFound = true;
target[i].put(entry.getKey(), entry.getValue());
}
}
if (!isFound) {
target[keys.length].put(entry.getKey(), entry.getValue());
}
}
}
return target;
}
/**
* This is a TEMPORARY method that will be removed.
* DON'T USE THIS METHOD - for internal use only.
*/
protected static void translateOldProperties(Map m, AbstractSession session) {
for(int i=0; i < oldPropertyNames.length; i++) {
Object value = getConfigPropertyAsString(oldPropertyNames[i][1], m);
if(value != null) {
if(session != null){
session.log(SessionLog.INFO, SessionLog.TRANSACTION, "deprecated_property", oldPropertyNames[i]);
}
m.put(oldPropertyNames[i][0], value);
}
}
}
protected static void warnOldProperties(Map m, AbstractSession session) {
for(int i=0; i < oldPropertyNames.length; i++) {
Object value = m.get(oldPropertyNames[i][1]);
if(value != null) {
session.log(SessionLog.INFO, SessionLog.TRANSACTION, "deprecated_property", oldPropertyNames[i]);
}
}
}
}