org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl 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, 2022 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2022 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
//
// 05/28/2008-1.0M8 Andrei Ilitchev
// - 224964: Provide support for Proxy Authentication through JPA.
// Added updateConnectionPolicy method to support EXCLUSIVE_CONNECTION property.
// Some methods, like setSessionEventListener called from deploy still used predeploy properties,
// that meant it was impossible to set listener through createEMF property in SE case with an agent - fixed that.
// Also if creating / closing the same emSetupImpl many times (24 in my case) "java.lang.OutOfMemoryError: PermGen space" resulted:
// partially fixed partially worked around this - see a big comment in predeploy method.
// 12/23/2008-1.1M5 Michael O'Brien
// - 253701: add persistenceInitializationHelper field used by undeploy() to clear the JavaSECMPInitializer
// 10/14/2009-2.0 Michael O'Brien
// - 266912: add Metamodel instance field as part of the JPA 2.0 implementation
// 10/21/2009-2.0 Guy Pelletier
// - 290567: mappedbyid support incomplete
// cdelahun - Bug 214534: changes to allow JMSPublishingTransportManager configuration through properties
// 05/14/2010-2.1 Guy Pelletier
// - 253083: Add support for dynamic persistence using ORM.xml/eclipselink-orm.xml
// 04/01/2011-2.3 Guy Pelletier
// - 337323: Multi-tenant with shared schema support (part 2)
// 06/30/2011-2.3.1 Guy Pelletier
// - 341940: Add disable/enable allowing native queries
// 09/20/2011-2.3.1 Guy Pelletier
// - 357476: Change caching default to ISOLATED for multitenant's using a shared EMF.
// 08/01/2012-2.5 Chris Delahunt
// - 371950: Metadata caching
// 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
// 08/11/2014-2.5 Rick Curtis
// - 440594: Tolerate invalid NamedQuery at EntityManager creation.
// 11/20/2014-2.5 Rick Curtis
// - 452187: Support multiple ClassLoaders to load properties.
// 01/05/2015 Rick Curtis
// - 455683: Automatically detect target server
// 01/13/2015 - Rick Curtis
// - 438871 : Add support for writing statement terminator character(s) when generating ddl to script.
// 02/19/2015 - Rick Curtis
// - 458877 : Add national character support
// 03/04/2015 - Will Dazey
// - 460862 : Added support for JTA schema generation without JTA-DS
// 03/23/2015 - Rick Curtis
// - 462888 : SessionCustomizer instance based configuration
// 08/24/2015 - Dalia Abo Sheasha
// - 475285 : Create a generic application-id property to generate unique session names
// 09/03/2015 - Will Dazey
// - 456067 : Added support for defining query timeout units
// 09/28/2015 - Will Dazey
// - 478331 : Added support for defining local or server as the default locale for obtaining timestamps
// 11/05/2015 - Dalia Abo Sheasha
// - 480787 : Wrap several privileged method calls with a doPrivileged block
// 12/03/2015-2.6 Dalia Abo Sheasha
// - 483582: Add the jakarta.persistence.sharedCache.mode property
// 09/29/2016-2.7 Tomas Kraus
// - 426852: @GeneratedValue(strategy=GenerationType.IDENTITY) support in Oracle 12c
// 09/14/2017-2.6 Will Dazey
// - 522312: Add the eclipselink.sequencing.start-sequence-at-nextval property
// 10/24/2017-3.0 Tomas Kraus
// - 526419: Modify EclipseLink to reflect changes in JTA 1.1.
// 01/16/2018-2.7 Joe Grassel
// - 529907: EntityManagerSetupImpl.addBeanValidationListeners() should fall back on old method for finding helperClass
// 12/06/2018 - Will Dazey
// - 542491: Add new 'eclipselink.jdbc.force-bind-parameters' property to force enable binding
// 09/02/2019-3.0 Alexandre Jacob
// - 527415: Fix code when locale is tr, az or lt
package org.eclipse.persistence.internal.jpa;
import static org.eclipse.persistence.config.PersistenceUnitProperties.DDL_GENERATION;
import static org.eclipse.persistence.config.PersistenceUnitProperties.NONE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_CREATE_ACTION;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_CREATE_DATABASE_SCHEMAS;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_CREATE_SCRIPT_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_CREATE_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_DATABASE_ACTION;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_DROP_ACTION;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_DROP_AND_CREATE_ACTION;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_DROP_SCRIPT_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_DROP_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_METADATA_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_METADATA_THEN_SCRIPT_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_NONE_ACTION;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_SCRIPTS_ACTION;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_SCRIPTS_CREATE_TARGET;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_SCRIPTS_DROP_TARGET;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_SCRIPT_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_SCRIPT_THEN_METADATA_SOURCE;
import static org.eclipse.persistence.config.PersistenceUnitProperties.SCHEMA_GENERATION_SQL_LOAD_SCRIPT_SOURCE;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.generateDefaultTables;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.getConfigProperty;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.getConfigPropertyAsString;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.getConfigPropertyLogDebug;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.hasConfigProperty;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.login;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.mergeMaps;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.translateOldProperties;
import static org.eclipse.persistence.internal.jpa.EntityManagerFactoryProvider.warnOldProperties;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.SharedCacheMode;
import jakarta.persistence.ValidationMode;
import jakarta.persistence.metamodel.Attribute;
import jakarta.persistence.metamodel.CollectionAttribute;
import jakarta.persistence.metamodel.ListAttribute;
import jakarta.persistence.metamodel.ManagedType;
import jakarta.persistence.metamodel.MapAttribute;
import jakarta.persistence.metamodel.Metamodel;
import jakarta.persistence.metamodel.SetAttribute;
import jakarta.persistence.metamodel.SingularAttribute;
import jakarta.persistence.spi.ClassTransformer;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.persistence.spi.PersistenceUnitTransactionType;
import org.eclipse.persistence.annotations.IdValidation;
import org.eclipse.persistence.config.BatchWriting;
import org.eclipse.persistence.config.CacheCoordinationProtocol;
import org.eclipse.persistence.config.CacheIsolationType;
import org.eclipse.persistence.config.DescriptorCustomizer;
import org.eclipse.persistence.config.ExclusiveConnectionMode;
import org.eclipse.persistence.config.LoggerType;
import org.eclipse.persistence.config.ParserType;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.ProfilerType;
import org.eclipse.persistence.config.RemoteProtocol;
import org.eclipse.persistence.config.SessionCustomizer;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.MultitenantPolicy;
import org.eclipse.persistence.descriptors.SchemaPerMultitenantPolicy;
import org.eclipse.persistence.descriptors.TimestampLockingPolicy;
import org.eclipse.persistence.descriptors.partitioning.PartitioningPolicy;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.eis.EISConnectionSpec;
import org.eclipse.persistence.eis.EISLogin;
import org.eclipse.persistence.eis.EISPlatform;
import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.EntityManagerSetupException;
import org.eclipse.persistence.exceptions.ExceptionHandler;
import org.eclipse.persistence.exceptions.IntegrityException;
import org.eclipse.persistence.exceptions.PersistenceUnitLoadingException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.BatchWritingMechanism;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy.LockOnChange;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConcurrencyManager;
import org.eclipse.persistence.internal.helper.ConcurrencyUtil;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.JPAClassLoaderHolder;
import org.eclipse.persistence.internal.helper.JPAConversionManager;
import org.eclipse.persistence.internal.jpa.deployment.BeanValidationInitializationHelper;
import org.eclipse.persistence.internal.jpa.deployment.PersistenceUnitProcessor;
import org.eclipse.persistence.internal.jpa.deployment.SEPersistenceUnitInfo;
import org.eclipse.persistence.internal.jpa.jdbc.DataSourceImpl;
import org.eclipse.persistence.internal.jpa.metadata.MetadataHelper;
import org.eclipse.persistence.internal.jpa.metadata.MetadataLogger;
import org.eclipse.persistence.internal.jpa.metadata.MetadataProcessor;
import org.eclipse.persistence.internal.jpa.metadata.MetadataProject;
import org.eclipse.persistence.internal.jpa.metadata.accessors.objects.MetadataAsmFactory;
import org.eclipse.persistence.internal.jpa.metadata.xml.XMLEntityMappingsReader;
import org.eclipse.persistence.internal.jpa.metamodel.ManagedTypeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.MetamodelImpl;
import org.eclipse.persistence.internal.jpa.metamodel.proxy.AttributeProxyImpl;
import org.eclipse.persistence.internal.jpa.metamodel.proxy.CollectionAttributeProxyImpl;
import org.eclipse.persistence.internal.jpa.metamodel.proxy.ListAttributeProxyImpl;
import org.eclipse.persistence.internal.jpa.metamodel.proxy.MapAttributeProxyImpl;
import org.eclipse.persistence.internal.jpa.metamodel.proxy.SetAttributeProxyImpl;
import org.eclipse.persistence.internal.jpa.metamodel.proxy.SingularAttributeProxyImpl;
import org.eclipse.persistence.internal.jpa.weaving.ClassDetails;
import org.eclipse.persistence.internal.jpa.weaving.PersistenceWeaver;
import org.eclipse.persistence.internal.jpa.weaving.TransformerFactory;
import org.eclipse.persistence.internal.localization.ExceptionLocalization;
import org.eclipse.persistence.internal.localization.LoggingLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedClassForName;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredField;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredFields;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredMethod;
import org.eclipse.persistence.internal.security.PrivilegedGetValueFromField;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.security.PrivilegedNewInstanceFromClass;
import org.eclipse.persistence.internal.security.SecurableObjectHolder;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.internal.sessions.PropertiesHandler;
import org.eclipse.persistence.internal.sessions.remote.RemoteConnection;
import org.eclipse.persistence.jpa.metadata.FileBasedProjectCache;
import org.eclipse.persistence.jpa.metadata.MetadataSource;
import org.eclipse.persistence.jpa.metadata.ProjectCache;
import org.eclipse.persistence.jpa.metadata.XMLMetadataSource;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.database.converters.StructConverter;
import org.eclipse.persistence.platform.database.events.DatabaseEventListener;
import org.eclipse.persistence.platform.database.partitioning.DataPartitioningCallback;
import org.eclipse.persistence.platform.server.CustomServerPlatform;
import org.eclipse.persistence.platform.server.ServerPlatform;
import org.eclipse.persistence.platform.server.ServerPlatformBase;
import org.eclipse.persistence.platform.server.ServerPlatformUtils;
import org.eclipse.persistence.queries.QueryResultsCachePolicy;
import org.eclipse.persistence.sequencing.Sequence;
import org.eclipse.persistence.sessions.Connector;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.DatasourceLogin;
import org.eclipse.persistence.sessions.DefaultConnector;
import org.eclipse.persistence.sessions.ExternalTransactionController;
import org.eclipse.persistence.sessions.JNDIConnector;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.SessionEventListener;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.broker.SessionBroker;
import org.eclipse.persistence.sessions.coordination.MetadataRefreshListener;
import org.eclipse.persistence.sessions.coordination.RemoteCommandManager;
import org.eclipse.persistence.sessions.coordination.TransportManager;
import org.eclipse.persistence.sessions.coordination.jms.JMSPublishingTransportManager;
import org.eclipse.persistence.sessions.coordination.jms.JMSTopicTransportManager;
import org.eclipse.persistence.sessions.coordination.rmi.RMITransportManager;
import org.eclipse.persistence.sessions.factories.SessionManager;
import org.eclipse.persistence.sessions.factories.XMLSessionConfigLoader;
import org.eclipse.persistence.sessions.remote.RemoteSession;
import org.eclipse.persistence.sessions.remote.rmi.RMIConnection;
import org.eclipse.persistence.sessions.remote.rmi.RMIServerSessionManager;
import org.eclipse.persistence.sessions.remote.rmi.RMIServerSessionManagerDispatcher;
import org.eclipse.persistence.sessions.serializers.JavaSerializer;
import org.eclipse.persistence.sessions.serializers.Serializer;
import org.eclipse.persistence.sessions.server.ConnectionPolicy;
import org.eclipse.persistence.sessions.server.ConnectionPool;
import org.eclipse.persistence.sessions.server.ExternalConnectionPool;
import org.eclipse.persistence.sessions.server.ReadConnectionPool;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.tools.profiler.PerformanceMonitor;
import org.eclipse.persistence.tools.profiler.PerformanceProfiler;
import org.eclipse.persistence.tools.profiler.QueryMonitor;
import org.eclipse.persistence.tools.schemaframework.SchemaManager;
import org.eclipse.persistence.tools.tuning.SafeModeTuner;
import org.eclipse.persistence.tools.tuning.SessionTuner;
import org.eclipse.persistence.tools.tuning.StandardTuner;
/**
* INTERNAL:
* This class handles deployment of a persistence unit.
* In predeploy the meta-data is processed and weaver transformer is returned to allow weaving of the persistent classes.
* In deploy the project and session are initialize and registered.
*/
public class EntityManagerSetupImpl implements MetadataRefreshListener {
/*
* Design Pattern in use: Builder pattern
* EntityManagerSetupImpl, MetadataProcessor and MetadataProject
* play the role of director, builder and product respectively.
* See processORMetadata which is the factory method.
*
*/
// this name should uniquely identify the persistence unit
protected String persistenceUnitUniqueName;
// session name should uniquely identify the session
protected String sessionName;
private MetadataProcessor processor = null;
/** Holds a reference to the weaver class transformer so it can be cleared after login. */
private PersistenceWeaver weaver = null;
protected PersistenceUnitInfo persistenceUnitInfo = null;
// count a number of open factories that use this object.
protected int factoryCount = 0;
protected AbstractSession session = null;
// true if predeploy called by createContainerEntityManagerFactory; false - createEntityManagerFactory
protected boolean isInContainerMode = false;
protected boolean isSessionLoadedFromSessionsXML=false;
//project caching:
protected ProjectCache projectCacheAccessor = null;
protected boolean shouldBuildProject = true;
// indicates whether weaving was used on the first run through predeploy (in STATE_INITIAL)
protected Boolean enableWeaving = null;
// indicates that classes have already been woven
protected boolean isWeavingStatic = false;
// used by static weaving
protected StaticWeaveInfo staticWeaveInfo;
protected SecurableObjectHolder securableObjectHolder = new SecurableObjectHolder();
// used by deploy method
protected ConcurrencyManager deployLock = new ConcurrencyManager();
protected boolean requiresConnection;
// 266912: Criteria API and Metamodel API (See Ch 5 of the JPA 2.0 Specification)
/** Reference to the Metamodel for this deployment and session.
* Please use the accessor and not the instance variable directly*/
private Metamodel metaModel;
protected List structConverters = null;
// factoryCount==0; session==null
public static final String STATE_INITIAL = "Initial";
// session != null
public static final String STATE_PREDEPLOYED = "Predeployed";
// factoryCount>0; session != null; session stored in SessionManager
// for compositeMember factoryCount is always 0; session is never stored in SessionBroker
// the session has not yet connected for the first time or failed to connect for the first time
public static final String STATE_HALF_DEPLOYED = "HalfDeployed";
// factoryCount>0; session != null; session stored in SessionManager
// for compositeMember factoryCount is always 0; session is never stored in SessionBroker
// the session has connected for the first time
public static final String STATE_DEPLOYED = "Deployed";
// factoryCount==0; session==null
public static final String STATE_PREDEPLOY_FAILED="PredeployFailed";
// factoryCount>0; session != null
// for compositeMember factoryCount is always 0
public static final String STATE_DEPLOY_FAILED = "DeployFailed";
// factoryCount==0; session==null
public static final String STATE_UNDEPLOYED = "Undeployed";
// factoryCount==0; session==null
// only composite member persistence unit can be in this state
public static final String STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER = "HalfPredeployedCompositeMember";
/**
* Initial -----> HalfPredeployedCompositeMember -----> PredeployFailed
* | ^ |
* V------->| V
* Predeployed
*/
protected String state = STATE_INITIAL;
/**
* Initial -----------> PredeployFailed ---
* | |
* V |
* Predeployed ---> DeployFailed -- |
* | | |
* V V V
* HalfDeployed --> Deployed -> Undeployed
* | ^
* V |
* DeployFailed -------------------
*
*/
public static final String ERROR_LOADING_XML_FILE = "error_loading_xml_file";
public static final String EXCEPTION_LOADING_ENTITY_CLASS = "exception_loading_entity_class";
/*
* Properties used to generate sessionName if none is provided.
*/
public static String[] connectionPropertyNames = {
PersistenceUnitProperties.TRANSACTION_TYPE,
PersistenceUnitProperties.JTA_DATASOURCE,
PersistenceUnitProperties.NON_JTA_DATASOURCE,
PersistenceUnitProperties.JDBC_URL,
PersistenceUnitProperties.JDBC_USER,
PersistenceUnitProperties.NOSQL_CONNECTION_SPEC,
PersistenceUnitProperties.NOSQL_CONNECTION_FACTORY,
PersistenceUnitProperties.NOSQL_USER,
PersistenceUnitProperties.JDBC_CONNECTOR
};
/*
* Composite, not null only if it's a composite member.
*/
protected EntityManagerSetupImpl compositeEmSetupImpl;
/*
* Composite members, not null only if it's a composite.
*/
protected Set compositeMemberEmSetupImpls;
/*
* In HalfPredeployedCompositeMember predeploy method called several times,
* each call uses mode, then updating it before returning.
* So mode value could be viewed as a substate of HalfPredeployedCompositeMember state.
* The mode is required for staging of processing OR metadata for composite members:
* each processing stage should be completed for ALL composite members before
* any one of then could proceed to the next processing stage.
*/
PersistenceUnitProcessor.Mode mode;
boolean throwExceptionOnFail;
boolean weaveChangeTracking;
boolean weaveLazy;
boolean weaveEager;
boolean weaveFetchGroups;
boolean weaveInternal;
boolean weaveRest;
boolean weaveMappedSuperClass;
/**
* Used to indicate that an EntityManagerFactoryImpl based on this
* EntityManagerSetupImpl has been refreshed. This means this EntityManagerSetupImpl
* will no longer be associated with new EntityManagerFactories
*/
protected boolean isMetadataExpired = false;
/*
* Used to distinguish the various DDL options
*/
protected enum TableCreationType {NONE, CREATE, DROP, DROP_AND_CREATE, EXTEND};
/*
* PersistenceException responsible for the invalid state.
*/
protected PersistenceException persistenceException;
public EntityManagerSetupImpl(String persistenceUnitUniqueName, String sessionName) {
this.persistenceUnitUniqueName = persistenceUnitUniqueName;
this.sessionName = sessionName;
this.requiresConnection = true;
}
public EntityManagerSetupImpl() {
this("", "");
}
protected static String addFileSeperator(String appLocation) {
int strLength = appLocation.length();
if (appLocation.substring(strLength -1, strLength).equals(File.separator)) {
return appLocation;
} else {
return appLocation + File.separator;
}
}
/*
* Return session name if specified.
* Otherwise build one from the connection properties names and values.
* Note that specifying value "" in properties causes
* the property value specified in PersistenceUnitInfo to be ignored.
* Never returns null.
*/
public static String getOrBuildSessionName(Map properties, PersistenceUnitInfo puInfo, String persistenceUnitUniqueName) {
// Weblogic server was found to prefix the file path on Windows platform with a slash, so mandating that for compatibility
String persistenceUnitName = assertCompatiblePersistenceUnitName(persistenceUnitUniqueName);
// if SESSION_NAME is specified in either properties or puInfo properties - use it as session name (unless it's an empty String).
String sessionName = (String)properties.get(PersistenceUnitProperties.SESSION_NAME);
if (sessionName == null) {
sessionName = (String)puInfo.getProperties().get(PersistenceUnitProperties.SESSION_NAME);
}
// Specifying empty String in properties allows to remove SESSION_NAME specified in puInfo properties.
if(sessionName != null && sessionName.length() > 0) {
return sessionName;
}
// ELBug 355603 - Prepend the application id if present in properties.
// This property will be set by the WebLogic Server if the persistence unit
// is deployed as part of shared library to construct a unique session name
String applicationId = (String)properties.get("weblogic.application-id");
// ELBug 475285 - Added a more generic version of the weblogic.application-id property.
if (applicationId == null) {
applicationId = (String) properties.get("eclipselink.application-id");
}
if (isComposite(puInfo)) {
// Composite doesn't use connection properties.
if (applicationId != null) {
return applicationId + persistenceUnitName;
}
return persistenceUnitName;
} else {
// In case no SESSION_NAME specified (or empty String) - build one
// by concatenating persistenceUnitUniqueName and suffix build of connection properties' names and values.
if (applicationId != null) {
return applicationId + persistenceUnitName + buildSessionNameSuffixFromConnectionProperties(properties);
}
return persistenceUnitName + buildSessionNameSuffixFromConnectionProperties(properties);
}
}
private static String assertCompatiblePersistenceUnitName(String persistenceUnitUniqueName) {
if(persistenceUnitUniqueName != null && !persistenceUnitUniqueName.startsWith("/")) {
return '/' + persistenceUnitUniqueName;
}
return persistenceUnitUniqueName;
}
protected static String buildSessionNameSuffixFromConnectionProperties(Map properties) {
StringBuilder suffix = new StringBuilder(32);
for (int i=0; i < connectionPropertyNames.length; i++) {
String name = connectionPropertyNames[i];
Object value = properties.get(name);
if (value != null) {
String strValue = null;
if (value instanceof String) {
strValue = (String)value;
} else {
if (value instanceof javax.sql.DataSource) {
// value of JTA_DATASOURCE / NON_JTA_DATASOURCE may be a DataSource (we would prefer DataSource name)
strValue = Integer.toString(System.identityHashCode(value));
} else if (value instanceof PersistenceUnitTransactionType) {
strValue = value.toString();
} else {
strValue = Integer.toString(System.identityHashCode(value));
}
}
// don't set an empty String
if (strValue.length() > 0) {
suffix.append("_").append(Helper.getShortClassName(name)).append("=").append(strValue);
}
}
}
return suffix.toString();
}
/*
* Should only be called when emSetupImpl created during SE initialization is set into a new EMF.
* emSetupImpl must be in PREDEPLOYED state.
*/
public void changeSessionName(String newSessionName) {
if(!session.getName().equals(newSessionName)) {
session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "session_name_change", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), newSessionName});
sessionName = newSessionName;
session.setName(newSessionName);
}
}
/**
* This method can be used to ensure the session represented by emSetupImpl
* is removed from the SessionManager.
*/
protected void removeSessionFromGlobalSessionManager() {
if (this.session != null){
try {
if (this.session.isDatabaseSession() && this.session.isConnected()) {
getDatabaseSession().logout();
}
} finally {
SessionManager manager = SessionManager.getManager();
manager.getSessions().remove(this.session.getName(), this.session);
manager.destroy();
}
}
}
/**
* Deploy a persistence session and return an EntityManagerFactory.
*
* Deployment takes a session that was partially created in the predeploy call and makes it whole.
*
* This means doing any configuration that requires the real class definitions for the entities. In
* the predeploy phase we were in a stage where we were not let allowed to load the real classes.
*
* Deploy could be called several times - but only the first call does the actual deploying -
* additional calls allow to update session properties (in case the session is not connected).
*
* Note that there is no need to synchronize deploy method - it doesn't alter factoryCount
* and while deploy is executed no other method can alter the current state
* (predeploy call would just increment factoryCount; undeploy call would not drop factoryCount to 0).
* However precautions should be taken to handle concurrent calls to deploy, because those may
* alter the current state or connect the session.
*
* @param realClassLoader The class loader that was used to load the entity classes. This loader
* will be maintained for the lifespan of the loaded classes.
* @param additionalProperties added to persistence unit properties for updateServerSession overriding existing properties.
* In JSE case it allows to alter properties in main (as opposed to preMain where preDeploy is called).
* @return An EntityManagerFactory to be used by the Container to obtain EntityManagers
*/
public AbstractSession deploy(ClassLoader realClassLoader, Map additionalProperties) {
if (this.state != STATE_PREDEPLOYED && this.state != STATE_DEPLOYED && this.state != STATE_HALF_DEPLOYED) {
if (mustBeCompositeMember()) {
throw new PersistenceException(EntityManagerSetupException.compositeMemberCannotBeUsedStandalone(this.persistenceUnitInfo.getPersistenceUnitName()));
}
throw new PersistenceException(EntityManagerSetupException.cannotDeployWithoutPredeploy(this.persistenceUnitInfo.getPersistenceUnitName(), this.state, this.persistenceException));
}
// state is PREDEPLOYED or DEPLOYED
this.session.log(SessionLog.FINEST, SessionLog.JPA, "deploy_begin", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), this.session.getName(), this.state, this.factoryCount});
ClassLoader classLoaderToUse = realClassLoader;
if (additionalProperties.containsKey(PersistenceUnitProperties.CLASSLOADER)) {
classLoaderToUse = (ClassLoader) additionalProperties.get(PersistenceUnitProperties.CLASSLOADER);
} else if ((this.processor != null) && (this.processor.getProject() != null) && (this.processor.getProject().hasVirtualClasses()) && (this.state == STATE_PREDEPLOYED) && (!(classLoaderToUse instanceof DynamicClassLoader))) {
classLoaderToUse = new DynamicClassLoader(classLoaderToUse);
}
// indicates whether session has failed to connect, determines whether HALF_DEPLOYED state should be kept in case of exception.
boolean isLockAcquired = false;
try {
Map deployProperties = mergeMaps(additionalProperties, this.persistenceUnitInfo.getProperties());
updateTunerPreDeploy(deployProperties, classLoaderToUse);
translateOldProperties(deployProperties, this.session);
if (isComposite()) {
updateCompositeMembersProperties(deployProperties);
}
if (this.state == STATE_PREDEPLOYED) {
this.deployLock.acquire();
isLockAcquired = true;
if (this.state == STATE_PREDEPLOYED) {
if (this.shouldBuildProject && !this.isSessionLoadedFromSessionsXML) {
if (isComposite()) {
deployCompositeMembers(deployProperties, classLoaderToUse);
} else {
if (this.processor.getMetadataSource() != null) {
Map metadataProperties = this.processor.getMetadataSource().getPropertyOverrides(deployProperties, classLoaderToUse, this.session.getSessionLog());
if (metadataProperties != null && !metadataProperties.isEmpty()) {
translateOldProperties(metadataProperties, this.session);
deployProperties = mergeMaps(metadataProperties, deployProperties);
}
}
// listeners and queries require the real classes and are therefore built during deploy using the realClassLoader
this.processor.setClassLoader(classLoaderToUse);
this.processor.createDynamicClasses();
this.processor.addEntityListeners();
if (this.projectCacheAccessor != null) {
//cache the project:
this.projectCacheAccessor.storeProject(this.session.getProject(), deployProperties, this.session.getSessionLog());
}
// The project is initially created using class names rather than classes. This call will make the conversion.
// If the session was loaded from sessions.xml this will also convert the descriptor classes to the correct class loader.
this.session.getProject().convertClassNamesToClasses(classLoaderToUse);
if (!isCompositeMember()) {
addBeanValidationListeners(deployProperties, classLoaderToUse);
}
// Process the customizers last.
this.processor.processCustomizers();
}
this.processor = null;
} else {
// The project is initially created using class names rather than classes. This call will make the conversion.
// If the session was loaded from sessions.xml this will also convert the descriptor classes to the correct class loader.
this.session.getProject().convertClassNamesToClasses(classLoaderToUse);
if (!this.shouldBuildProject) {
//process anything that might not have been serialized/cached in the project correctly:
if (!isCompositeMember()) {
addBeanValidationListeners(deployProperties, classLoaderToUse);
}
//process Descriptor customizers:
processDescriptorsFromCachedProject(classLoaderToUse);
}
}
finishProcessingDescriptorEvents(classLoaderToUse);
this.structConverters = getStructConverters(classLoaderToUse);
updateRemote(deployProperties, classLoaderToUse);
initSession();
if (this.session.getIntegrityChecker().hasErrors()){
this.session.handleException(new IntegrityException(session.getIntegrityChecker()));
}
this.session.getDatasourcePlatform().getConversionManager().setLoader(classLoaderToUse);
this.state = STATE_HALF_DEPLOYED;
// keep deployLock
} else {
// state is HALF_DEPLOYED or DEPLOY_FAILED
this.deployLock.release();
isLockAcquired = false;
if (this.state == STATE_DEPLOY_FAILED) {
// while this thread waited in STATE_PREDEPLOYED another thread attempted to deploy and failed.
// Rethrow the cache PersistenceException, which caused STATE_DEPLOYED_FAILED.
throw persistenceException;
}
}
}
// state is HALF_DEPLOYED or DEPLOYED
if (!isCompositeMember()) {
if (this.session.isDatabaseSession() && !((DatabaseSessionImpl)session).isLoggedIn()) {
// If it's HALF_DEPLOYED then deployLock has been already acquired.
if (!isLockAcquired) {
this.deployLock.acquire();
isLockAcquired = true;
}
if (!((DatabaseSessionImpl)this.session).isLoggedIn()) {
if (this.state == STATE_DEPLOY_FAILED) {
// while this thread waited in STATE_HALF_DEPLOYED another thread attempted to connect the session and failed.
// Rethrow the cache PersistenceException, which caused STATE_DEPLOYED_FAILED.
throw persistenceException;
}
this.session.setProperties(deployProperties);
updateSession(deployProperties, classLoaderToUse);
if (isValidationOnly(deployProperties, false)) {
/**
* for 324213 we could add a session.loginAndDetectDatasource() call
* before calling initializeDescriptors when validation-only is True
* to avoid a native sequence exception on a generic DatabasePlatform
* by auto-detecting the correct DB platform.
* However, this would introduce a DB login when validation is on
* - in opposition to the functionality of the property (to only validate)
*/
if (this.state == STATE_HALF_DEPLOYED) {
getDatabaseSession().initializeDescriptors();
this.state = STATE_DEPLOYED;
}
} else {
try {
updateTunerDeploy(deployProperties, classLoaderToUse);
updateFreeMemory(deployProperties);
if (this.isSessionLoadedFromSessionsXML) {
getDatabaseSession().login();
} else {
login(getDatabaseSession(), deployProperties, requiresConnection);
}
// Make JTA integration throw JPA exceptions.
if (this.session.hasExternalTransactionController()) {
if (this.session.getExternalTransactionController().getExceptionHandler() == null) {
this.session.getExternalTransactionController().setExceptionHandler(new ExceptionHandler() {
@Override
public Object handleException(RuntimeException exception) {
if (exception instanceof org.eclipse.persistence.exceptions.OptimisticLockException) {
throw new OptimisticLockException(exception);
} else if (exception instanceof EclipseLinkException) {
throw new PersistenceException(exception);
} else {
throw exception;
}
}
});
}
}
this.state = STATE_DEPLOYED;
} catch (Throwable loginException) {
if (this.state == STATE_HALF_DEPLOYED) {
if (this.session.isConnected()) {
// session is connected, but postConnect has failed.
// Likely this is caused by failure in initializeDescriptors:
// either descriptor exception or by invalid named jpql query.
// Cannot recover from that - the user has to fix the persistence unit and redeploy it.
try {
getDatabaseSession().logout();
} catch (Throwable logoutException) {
// Ignore
}
this.state = STATE_DEPLOY_FAILED;
}
}
throw loginException;
}
if (!this.isSessionLoadedFromSessionsXML) {
addStructConverters();
}
// Generate the DDL using the correct connection.
writeDDL(deployProperties, getDatabaseSession(deployProperties), classLoaderToUse);
}
}
// Initialize platform specific identity sequences.
session.getDatasourcePlatform().initIdentitySequences(getDatabaseSession(), MetadataProject.DEFAULT_IDENTITY_GENERATOR);
updateTunerPostDeploy(deployProperties, classLoaderToUse);
this.deployLock.release();
isLockAcquired = false;
}
// 266912: Initialize the Metamodel, a login should have already occurred.
try {
this.getMetamodel(classLoaderToUse);
} catch (Exception e) {
this.session.log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_init_failed", new Object[]{e.getMessage()});
}
}
// Clear the weaver's reference to meta-data information, as it is held by the class loader and will never gc.
if (this.weaver != null) {
this.weaver.clear();
this.weaver = null;
}
return this.session;
} catch (Throwable exception) {
// before releasing deployLock switch to the correct state
if (this.state == STATE_PREDEPLOYED) {
this.state = STATE_DEPLOY_FAILED;
}
PersistenceException persistenceEx;
if (this.state == STATE_DEPLOY_FAILED) {
if (exception == persistenceException) {
persistenceEx = new PersistenceException(EntityManagerSetupException.cannotDeployWithoutPredeploy(this.persistenceUnitInfo.getPersistenceUnitName(), this.state, this.persistenceException));
} else {
// before releasing deployLock cache the exception
persistenceEx = createDeployFailedPersistenceException(exception);
}
} else {
if (exception instanceof PersistenceException) {
persistenceEx = (PersistenceException)exception;
} else {
persistenceEx = new PersistenceException(exception);
}
}
if (isLockAcquired) {
this.deployLock.release();
}
this.session.logThrowable(SessionLog.SEVERE, SessionLog.EJB, exception);
throw persistenceEx;
} finally {
this.session.log(SessionLog.FINEST, SessionLog.JPA, "deploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), this.session.getName(), this.state, this.factoryCount});
}
}
/**
* INTERNAL:
* This method is used to resolve Descriptor Customizers that might have been stored in the project
* for JPA project caching.
*
* @param realClassLoader
* @throws ClassNotFoundException
* @throws PrivilegedActionException
* @throws IllegalAccessException
* @throws InstantiationException
*/
private void processDescriptorsFromCachedProject(ClassLoader realClassLoader) throws ClassNotFoundException, PrivilegedActionException, IllegalAccessException, InstantiationException {
for (ClassDescriptor descriptor: session.getProject().getDescriptors().values()) {
//process customizers:
if (descriptor.getDescriptorCustomizerClassName() != null) {
Class listenerClass = findClass(descriptor.getDescriptorCustomizerClassName(), realClassLoader);
DescriptorCustomizer customizer = (DescriptorCustomizer) buildObjectForClass(listenerClass, DescriptorCustomizer.class);
try {
customizer.customize(descriptor);
} catch (Exception e) {
session.getSessionLog().logThrowable(SessionLog.FINER, SessionLog.METADATA, e);
}
}
}
}
/**
* INTERNAL:
* This method is used to resolve Descriptor Events processed earlier into EventHolders that now need to be
* used to create the DescriptorEventListeners and added to the DescriptorEventManager
*
*/
private void finishProcessingDescriptorEvents(ClassLoader realClassLoader) {
for (ClassDescriptor descriptor: session.getProject().getDescriptors().values()) {
if (descriptor.hasEventManager()) {
descriptor.getEventManager().processDescriptorEventHolders(session, realClassLoader);
}
}
}
protected PersistenceException createDeployFailedPersistenceException(Throwable ex) {
PersistenceException perEx = new PersistenceException(EntityManagerSetupException.deployFailed(persistenceUnitInfo.getPersistenceUnitName(), ex));
if (persistenceException == null) {
persistenceException = perEx;
}
return perEx;
}
/**
* Adds descriptors plus sequencing info found on the project to the session.
*/
protected void addProjectToSession(ServerSession session, Project project) {
DatasourcePlatform sessionPlatform = (DatasourcePlatform)session.getDatasourceLogin().getDatasourcePlatform();
DatasourcePlatform projectPlatform = (DatasourcePlatform)project.getDatasourceLogin().getDatasourcePlatform();
if (!sessionPlatform.hasDefaultSequence() && projectPlatform.hasDefaultSequence()) {
sessionPlatform.setDefaultSequence(projectPlatform.getDefaultSequence());
}
if ((sessionPlatform.getSequences() == null) || sessionPlatform.getSequences().isEmpty()) {
if ((projectPlatform.getSequences() != null) && !projectPlatform.getSequences().isEmpty()) {
sessionPlatform.setSequences(projectPlatform.getSequences());
}
} else {
if ((projectPlatform.getSequences() != null) && !projectPlatform.getSequences().isEmpty()) {
Iterator itProjectSequences = projectPlatform.getSequences().values().iterator();
while (itProjectSequences.hasNext()) {
Sequence sequence = (Sequence)itProjectSequences.next();
if (!sessionPlatform.getSequences().containsKey(sequence.getName())) {
sessionPlatform.addSequence(sequence);
}
}
}
}
session.addDescriptors(project);
}
/**
* Put the given session into the session manager so it can be looked up later
*/
protected void addSessionToGlobalSessionManager() {
SessionManager sm = SessionManager.getManager();
ConcurrentMap sessions = sm.getSessions();
AbstractSession oldSession = (AbstractSession) sessions.get(session.getName());
if(oldSession != null) {
throw new PersistenceException(EntityManagerSetupException.attemptedRedeployWithoutClose(session.getName()));
}
sm.addSession(session);
}
/**
* Add the StructConverters that were specified by annotation on the DatabasePlatform
* This method must be called after the DatabasePlatform has been detected
*/
public void addStructConverters(){
if (this.compositeMemberEmSetupImpls == null) {
for (StructConverter structConverter : structConverters){
if (session.getPlatform().getTypeConverters().get(structConverter.getJavaType()) != null){
throw ValidationException.twoStructConvertersAddedForSameClass(structConverter.getJavaType().getName());
}
session.getPlatform().addStructConverter(structConverter);
}
} else {
// composite
for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) {
if (!compositeMemberEmSetupImpl.structConverters.isEmpty()) {
String compositeMemberPuName = compositeMemberEmSetupImpl.getPersistenceUnitInfo().getPersistenceUnitName();
// debug output added to make it easier to navigate the log because the method is called outside of composite member deploy
compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_begin_call", new Object[]{"addStructConverters", compositeMemberPuName, state});
compositeMemberEmSetupImpl.addStructConverters();
compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_end_call", new Object[]{"addStructConverters", compositeMemberPuName, state});
}
}
}
}
/**
* Assign a CMP3Policy to each descriptor, and sets the OptimisticLockingPolicy's LockOnChangeMode if applicable.
*/
protected void assignCMP3Policy() {
// all descriptors assigned CMP3Policy
Project project = session.getProject();
for (Iterator iterator = project.getDescriptors().values().iterator(); iterator.hasNext();){
//bug:4406101 changed class cast to base class, which is used in projects generated from 904 xml
ClassDescriptor descriptor = (ClassDescriptor)iterator.next();
if(descriptor.getCMPPolicy() == null) {
descriptor.setCMPPolicy(new CMP3Policy());
}
OptimisticLockingPolicy olp = descriptor.getOptimisticLockingPolicy();
if (olp != null && olp.getLockOnChangeMode() == null){
olp.setLockOnChangeMode(LockOnChange.OWNING);
}
}
// TODO: Look into setting a CMPPolicy on the MappedSuperclass descriptors.
// Will require some tweaking however to ensure the primary key fields are
// set/initialized correctly. Currently rely on the descriptor initialized
// object builder which is not available to mapped superclass descriptors.
}
/**
* Updates the EclipseLink ServerPlatform class for use with this platform.
* @return true if the ServerPlatform has changed.
*/
protected boolean updateServerPlatform(Map m, ClassLoader loader) {
final String serverPlatformClassNameProperty =
PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.TARGET_SERVER, m, session);
final String jtaControllerClassNameProperty =
PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.JTA_CONTROLLER, m, session);
final String serverPlatformClassName;
if (serverPlatformClassNameProperty == null) {
// property is not specified - try to detect.
serverPlatformClassName = ServerPlatformUtils.detectServerPlatform(getSession());
if (serverPlatformClassName == null) {
// Unable to detect what platform we're running on. Use default/NoServer.
return false;
}
} else {
serverPlatformClassName = serverPlatformClassNameProperty;
}
// originalServerPlatform is always non-null - Session's constructor sets serverPlatform to NoServerPlatform
final ServerPlatform originalServerPlatform = session.getServerPlatform();
final String originalServerPlatformClassName = originalServerPlatform.getClass().getName();
final Class originalServerPlatformTransCtrlClass = originalServerPlatform.getExternalTransactionControllerClass();
final String originalServerPlatformTransCtrlClassName = originalServerPlatformTransCtrlClass != null
? originalServerPlatform.getExternalTransactionControllerClass().getName() : null;
if (serverPlatformClassName.equals(originalServerPlatformClassName)
&& (serverPlatformClassNameProperty == null || serverPlatformClassNameProperty.equals(originalServerPlatformClassName))
&& (jtaControllerClassNameProperty == null || jtaControllerClassNameProperty.equals(originalServerPlatformTransCtrlClassName))) {
// nothing to do - use the same value as before
return false;
}
// the new serverPlatform
ServerPlatform serverPlatform = null;
// New platform - create the new instance and set it.
Class cls = findClassForProperty(serverPlatformClassName, PersistenceUnitProperties.TARGET_SERVER, loader);
boolean isTargetServerTransCtrl = false;
try {
Constructor constructor = cls.getConstructor(new Class[]{org.eclipse.persistence.sessions.DatabaseSession.class});
serverPlatform = (ServerPlatform)constructor.newInstance(new Object[]{session});
} catch (Exception ex) {
if(ExternalTransactionController.class.isAssignableFrom(cls)) {
// the new serverPlatform is CustomServerPlatform, cls is its ExternalTransactionController class
if(originalServerPlatform.getClass().equals(CustomServerPlatform.class)) {
// both originalServerPlatform and the new serverPlatform are Custom,
// just set externalTransactionController class (if necessary) into
// originalServerPlatform
CustomServerPlatform originalCustomServerPlatform = (CustomServerPlatform)originalServerPlatform;
if (cls.equals(originalCustomServerPlatform.getExternalTransactionControllerClass())) {
// externalTransactionController classes are the same - nothing to do
} else {
originalCustomServerPlatform.setExternalTransactionControllerClass(cls);
}
} else {
// originalServerPlatform is not custom - need a new one.
serverPlatform = new CustomServerPlatform(getDatabaseSession());
serverPlatform.setExternalTransactionControllerClass(cls);
}
isTargetServerTransCtrl = true;
} else {
throw EntityManagerSetupException.failedToInstantiateServerPlatform(serverPlatformClassName, PersistenceUnitProperties.TARGET_SERVER, ex);
}
}
// Override JTA transaction controller class by eclipselink.jta.controller property, but only when
// eclipselink.target-server does not contain ExternalTransactionController implementing class.
if (jtaControllerClassNameProperty != null) {
if (isTargetServerTransCtrl) {
session.getSessionLog().log(SessionLog.WARNING, "jta_duplicate_ctrl_property");
} else {
if (!originalServerPlatform.getClass().equals(CustomServerPlatform.class)) {
serverPlatform = new CustomServerPlatform(getDatabaseSession());
}
updateJTAControllerInPlatform(serverPlatform != null ? serverPlatform : originalServerPlatform, jtaControllerClassNameProperty, loader);
}
}
if (serverPlatform != null) {
getDatabaseSession().setServerPlatform(serverPlatform);
return true;
}
return false;
}
/**
* Update JTA transaction controller class of provided {@link ServerPlatform} instance.
*
* @param serverPlatform target {@link ServerPlatform} instance
* @param jtaControllerClassName JTA transaction controller class name
* @param loader class loader containing JTA transaction controller class
*/
private static void updateJTAControllerInPlatform(
final ServerPlatform serverPlatform, final String jtaControllerClassName, final ClassLoader loader) {
Class jtaCls = findClassForProperty(jtaControllerClassName, PersistenceUnitProperties.JTA_CONTROLLER, loader);
serverPlatform.setExternalTransactionControllerClass(jtaCls);
}
/**
* Checks for partitioning properties.
*/
protected void updatePartitioning(Map m, ClassLoader loader) {
// Partitioning
String partitioning = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.PARTITIONING, m, this.session);
if (partitioning != null) {
PartitioningPolicy partitioningPolicy = this.session.getProject().getPartitioningPolicy(partitioning);
if (partitioningPolicy == null) {
throw DescriptorException.missingPartitioningPolicy(partitioning, null, null);
}
this.session.setPartitioningPolicy(partitioningPolicy);
}
String callbackClassName = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.PARTITIONING_CALLBACK, m, this.session);
if (callbackClassName != null) {
Class cls = findClassForProperty(callbackClassName, PersistenceUnitProperties.PARTITIONING_CALLBACK, loader);
DataPartitioningCallback callback = null;
try {
Constructor constructor = cls.getConstructor();
callback = (DataPartitioningCallback)constructor.newInstance();
} catch (Exception exception) {
throw EntityManagerSetupException.failedToInstantiateProperty(callbackClassName, PersistenceUnitProperties.PARTITIONING_CALLBACK, exception);
}
this.session.getLogin().setPartitioningCallback(callback);
}
}
/**
* Checks for partitioning properties.
*/
protected void updateRemote(Map m, ClassLoader loader) {
String protocol = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.REMOTE_PROTOCOL, m, this.session);
String serverName = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.REMOTE_SERVER_NAME, m, this.session);
if (serverName == null) {
// Configure as client.
if (protocol != null) {
RemoteConnection connection = null;
if (protocol.equalsIgnoreCase(RemoteProtocol.RMI)) {
String url = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.REMOTE_URL, m, this.session);
if (url == null) {
throw EntityManagerSetupException.missingProperty(PersistenceUnitProperties.REMOTE_URL);
}
try {
connection = new RMIConnection(((RMIServerSessionManager)Naming.lookup(url)).createRemoteSessionController());
} catch (Exception exception) {
throw ValidationException.invalidValueForProperty(url, PersistenceUnitProperties.REMOTE_URL, exception);
}
} else {
Class cls = findClassForProperty(protocol, PersistenceUnitProperties.REMOTE_PROTOCOL, loader);
try {
Constructor constructor = cls.getConstructor();
connection = (RemoteConnection)constructor.newInstance();
} catch (Exception exception) {
throw ValidationException.invalidValueForProperty(protocol, PersistenceUnitProperties.REMOTE_PROTOCOL, exception);
}
}
RemoteSession remoteSession = new RemoteSession();
remoteSession.setIsMetadataRemote(false);
remoteSession.setProject(this.session.getProject());
remoteSession.setProfiler(this.session.getProfiler());
remoteSession.setSessionLog(this.session.getSessionLog());
remoteSession.setEventManager(this.session.getEventManager());
remoteSession.setQueries(this.session.getQueries());
remoteSession.setProperties(this.session.getProperties());
remoteSession.setName(this.session.getName());
remoteSession.setRemoteConnection(connection);
this.session = remoteSession;
}
} else {
// Configure as server.
if (protocol.equalsIgnoreCase(RemoteProtocol.RMI)) {
RMIServerSessionManager manager = null;
// Make sure RMI registry is started.
try {
java.rmi.registry.LocateRegistry.createRegistry(1099);
} catch (Exception exception) {
System.out.println("Security violation " + exception.toString());
}
// Create local instance of the factory
try {
manager = new RMIServerSessionManagerDispatcher(session);
} catch (RemoteException exception) {
throw ValidationException.invalidValueForProperty(serverName, PersistenceUnitProperties.REMOTE_SERVER_NAME, exception);
}
// Put the local instance into the Registry
try {
Naming.unbind(serverName);
} catch (Exception exception) {
// Ignore.
}
// Put the local instance into the Registry
try {
Naming.rebind(serverName, manager);
} catch (Exception exception) {
throw ValidationException.invalidValueForProperty(serverName, PersistenceUnitProperties.REMOTE_SERVER_NAME, exception);
}
}
}
}
/**
* Checks for database events listener properties.
*/
protected void updateDatabaseEventListener(Map m, ClassLoader loader) {
String listenerClassName = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.DATABASE_EVENT_LISTENER, m, this.session);
if (listenerClassName != null) {
if (listenerClassName.equalsIgnoreCase("DCN") || listenerClassName.equalsIgnoreCase("QCN")) {
listenerClassName = "org.eclipse.persistence.platform.database.oracle.dcn.OracleChangeNotificationListener";
}
Class cls = findClassForProperty(listenerClassName, PersistenceUnitProperties.DATABASE_EVENT_LISTENER, loader);
DatabaseEventListener listener = null;
try {
Constructor constructor = cls.getConstructor();
listener = (DatabaseEventListener)constructor.newInstance();
} catch (Exception exception) {
throw EntityManagerSetupException.failedToInstantiateProperty(listenerClassName, PersistenceUnitProperties.DATABASE_EVENT_LISTENER, exception);
}
getDatabaseSession().setDatabaseEventListener(listener);
}
}
/**
* Update loggers and settings for the singleton logger and the session logger.
* @param persistenceProperties the properties map
* @param serverPlatformChanged the boolean that denotes a serverPlatform change in the session.
*/
protected void updateLoggers(Map persistenceProperties, boolean serverPlatformChanged, ClassLoader loader) {
// Logger(SessionLog type) can be specified by the logger property or ServerPlatform.getServerLog().
// The logger property has a higher priority to ServerPlatform.getServerLog().
String loggerClassName = PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.LOGGING_LOGGER, persistenceProperties, session);
// The sessionLog instance should be different from the singletonLog because they have
// different state.
SessionLog singletonLog = null, sessionLog = null;
if (loggerClassName != null) {
SessionLog currentLog = session.getSessionLog();
if(loggerClassName.equals(LoggerType.ServerLogger)){
ServerPlatform serverPlatform = session.getServerPlatform();
singletonLog = serverPlatform.getServerLog();
sessionLog = serverPlatform.getServerLog();
} else if (!currentLog.getClass().getName().equals(loggerClassName)) {
// Logger class was specified and it's not what's already there.
Class sessionLogClass = findClassForProperty(loggerClassName, PersistenceUnitProperties.LOGGING_LOGGER, loader);
try {
singletonLog = (SessionLog)sessionLogClass.getConstructor().newInstance();
sessionLog = (SessionLog)sessionLogClass.getConstructor().newInstance();
} catch (Exception ex) {
throw EntityManagerSetupException.failedToInstantiateLogger(loggerClassName, PersistenceUnitProperties.LOGGING_LOGGER, ex);
}
}
} else if (serverPlatformChanged) {
ServerPlatform serverPlatform = session.getServerPlatform();
singletonLog = serverPlatform.getServerLog();
sessionLog = serverPlatform.getServerLog();
}
// Don't change default loggers if the new loggers have not been created.
if (singletonLog != null && sessionLog != null) {
AbstractSessionLog.setLog(singletonLog);
session.setSessionLog(sessionLog);
}
// Bug5389828. Update the logging settings for the singleton logger.
initOrUpdateLogging(persistenceProperties, AbstractSessionLog.getLog());
initOrUpdateLogging(persistenceProperties, session.getSessionLog());
// Set logging file.
String loggingFileString = (String)persistenceProperties.get(PersistenceUnitProperties.LOGGING_FILE);
if (loggingFileString != null) {
if (!loggingFileString.trim().equals("")) {
try {
if (sessionLog!=null){
if (sessionLog instanceof AbstractSessionLog) {
FileOutputStream fos = new FileOutputStream(loggingFileString);
((AbstractSessionLog)sessionLog).setWriter(fos);
} else {
FileWriter fw = new FileWriter(loggingFileString);
sessionLog.setWriter(fw);
}
}
} catch (IOException e) {
session.handleException(ValidationException.invalidLoggingFile(loggingFileString,e));
}
} else {
session.handleException(ValidationException.invalidLoggingFile());
}
}
}
/**
* Check for the PROFILER persistence or system property and set the Session's profiler.
* This can also set the QueryMonitor.
*/
protected void updateProfiler(Map persistenceProperties,ClassLoader loader) {
// This must use config property as the profiler is not in the PropertiesHandler and requires
// supporting generic profiler classes.
String newProfilerClassName = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.PROFILER, persistenceProperties, session);
if (newProfilerClassName == null) {
ServerPlatformBase plaftorm = ((ServerPlatformBase)session.getServerPlatform());
if (plaftorm != null) {
plaftorm.configureProfiler(session);
}
} else {
if (newProfilerClassName.equals(ProfilerType.NoProfiler)) {
session.setProfiler(null);
return;
}
if (newProfilerClassName.equals(ProfilerType.QueryMonitor)) {
session.setProfiler(null);
QueryMonitor.shouldMonitor=true;
return;
}
if (newProfilerClassName.equals(ProfilerType.PerformanceProfiler)) {
session.setProfiler(new PerformanceProfiler());
return;
}
if (newProfilerClassName.equals(ProfilerType.PerformanceMonitor)) {
session.setProfiler(new PerformanceMonitor());
return;
}
if (newProfilerClassName.equals(ProfilerType.DMSProfiler)) {
newProfilerClassName = ProfilerType.DMSProfilerClassName;
}
String originalProfilerClassNamer = null;
if (session.getProfiler() != null) {
originalProfilerClassNamer = session.getProfiler().getClass().getName();
if (originalProfilerClassNamer.equals(newProfilerClassName)) {
return;
}
}
// New profiler - create the new instance and set it.
try {
Class newProfilerClass = findClassForProperty(newProfilerClassName, PersistenceUnitProperties.PROFILER, loader);
SessionProfiler sessionProfiler = (SessionProfiler)buildObjectForClass(newProfilerClass, SessionProfiler.class);
if (sessionProfiler != null) {
session.setProfiler(sessionProfiler);
} else {
session.handleException(ValidationException.invalidProfilerClass(newProfilerClassName));
}
} catch (IllegalAccessException e) {
session.handleException(ValidationException.cannotInstantiateProfilerClass(newProfilerClassName,e));
} catch (PrivilegedActionException e) {
session.handleException(ValidationException.cannotInstantiateProfilerClass(newProfilerClassName,e));
} catch (InstantiationException e) {
session.handleException(ValidationException.cannotInstantiateProfilerClass(newProfilerClassName,e));
}
}
}
protected static Class findClass(String className, ClassLoader loader) throws ClassNotFoundException, PrivilegedActionException {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
return AccessController.doPrivileged(new PrivilegedClassForName(className, true, loader));
} else {
return org.eclipse.persistence.internal.security.PrivilegedAccessHelper.getClassForName(className, true, loader);
}
}
protected static Class findClassForProperty(String className, String propertyName, ClassLoader loader) {
ClassLoader eclipselinkLoader = EntityManagerSetupImpl.class.getClassLoader();
boolean multipleLoaders = eclipselinkLoader != loader;
if (multipleLoaders) {
return findClassForPropertyInternal(className, propertyName, loader, eclipselinkLoader);
} else {
return findClassForPropertyInternal(className, propertyName, loader);
}
}
private static Class findClassForPropertyInternal(String clsName, String propName, ClassLoader... loaders) {
RuntimeException e = null;
for (ClassLoader loader : loaders) {
try {
return findClass(clsName, loader);
} catch (PrivilegedActionException exception1) {
e = EntityManagerSetupException.classNotFoundForProperty(clsName, propName, exception1.getException());
} catch (ClassNotFoundException exception2) {
e = EntityManagerSetupException.classNotFoundForProperty(clsName, propName, exception2);
}
}
throw e;
}
/**
* Internal:
* Returns a list of StructConverter instances from a list of StructConverter names stored within the project.
*
* @param realClassLoader
* @return
*/
protected List getStructConverters(ClassLoader realClassLoader) {
List structConverters = new ArrayList();
if (session.getProject().getStructConverters() != null) {
for (String converter: session.getProject().getStructConverters()) {
Class clazz = null;
try {
clazz = findClass(converter, realClassLoader);
} catch (PrivilegedActionException exception) {
throw ValidationException.unableToLoadClass(converter, exception.getException());
} catch (ClassNotFoundException exception) {
throw ValidationException.unableToLoadClass(converter, exception);
}
try {
structConverters.add((StructConverter) buildObjectForClass(clazz, StructConverter.class));
} catch (PrivilegedActionException e) {
throw ValidationException.errorInstantiatingClass(clazz, e.getException());
} catch (IllegalAccessException e) {
throw ValidationException.errorInstantiatingClass(clazz, e);
} catch (InstantiationException e) {
throw ValidationException.errorInstantiatingClass(clazz, e);
}
}
}
return structConverters;
}
protected boolean hasSchemaDatabaseGeneration(Map m) {
if (hasConfigProperty(SCHEMA_GENERATION_DATABASE_ACTION, m)) {
return getConfigPropertyAsString(SCHEMA_GENERATION_DATABASE_ACTION, m) != null && ! getConfigPropertyAsString(SCHEMA_GENERATION_DATABASE_ACTION, m).equals(SCHEMA_GENERATION_NONE_ACTION);
}
return false;
}
protected boolean hasSchemaScriptsGeneration(Map m) {
if (hasConfigProperty(SCHEMA_GENERATION_SCRIPTS_ACTION, m)) {
return getConfigPropertyAsString(SCHEMA_GENERATION_SCRIPTS_ACTION, m) != null && ! getConfigPropertyAsString(SCHEMA_GENERATION_SCRIPTS_ACTION, m).equals(SCHEMA_GENERATION_NONE_ACTION);
}
return false;
}
public AbstractSession getSession() {
return session;
}
public DatabaseSessionImpl getDatabaseSession() {
return (DatabaseSessionImpl)session;
}
/**
* We may be provided a connection via the properties to use. Check for
* one and build a database session around it. Otherwise return the pu
* database session.
*/
public DatabaseSessionImpl getDatabaseSession(Map props) {
DatabaseSessionImpl databaseSession = getDatabaseSession();
Object connection = getConfigProperty(PersistenceUnitProperties.SCHEMA_GENERATION_CONNECTION, props);
if (connection == null) {
return databaseSession;
} else {
// A connection was provided. Build a database session using that
// connection and use the same log level set on the original
// database session.
DatabaseSessionImpl newDatabaseSession = new DatabaseSessionImpl();
newDatabaseSession.setAccessor(new DatabaseAccessor(connection));
newDatabaseSession.setLogLevel(databaseSession.getLogLevel());
newDatabaseSession.setProject(databaseSession.getProject().clone());
return newDatabaseSession;
}
}
/**
* This method will be used to validate the specified class and return it's instance.
*/
protected static Object buildObjectForClass(Class clazz, Class mustBeImplementedInterface) throws IllegalAccessException, PrivilegedActionException,InstantiationException {
if(clazz!=null && Helper.classImplementsInterface(clazz,mustBeImplementedInterface)){
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
return AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(clazz));
} else {
return PrivilegedAccessHelper.newInstanceFromClass(clazz);
}
} else {
return null;
}
}
protected void updateDescriptorCacheSettings(Map m, ClassLoader loader) {
String queryCache = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.QUERY_CACHE, m, session);
if ((queryCache != null) && queryCache.equalsIgnoreCase("true")) {
session.getProject().setDefaultQueryResultsCachePolicy(new QueryResultsCachePolicy());
}
String queryCacheForceDeferredLocks = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CACHE_QUERY_FORCE_DEFERRED_LOCKS, m, session);
if ((queryCacheForceDeferredLocks != null) && queryCacheForceDeferredLocks.equalsIgnoreCase("true")) {
session.getProject().setQueryCacheForceDeferredLocks(true);
} else {
session.getProject().setQueryCacheForceDeferredLocks(false);
}
Map typeMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CACHE_TYPE_, m, session);
Map sizeMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CACHE_SIZE_, m, session);
Map sharedMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CACHE_SHARED_, m, session);
if(typeMap.isEmpty() && sizeMap.isEmpty() && sharedMap.isEmpty()) {
return;
}
String defaultTypeName = (String)typeMap.remove(PersistenceUnitProperties.DEFAULT);
if (defaultTypeName != null) {
// Always use the EclipseLink class loader, otherwise can have loader/redeployment issues.
Class defaultType = findClassForProperty(defaultTypeName, PersistenceUnitProperties.CACHE_TYPE_DEFAULT, getClass().getClassLoader());
session.getProject().setDefaultIdentityMapClass(defaultType);
}
String value = null;
try {
String defaultSizeString = (String)sizeMap.remove(PersistenceUnitProperties.DEFAULT);
if (defaultSizeString != null) {
value = defaultSizeString;
int defaultSize = Integer.parseInt(defaultSizeString);
session.getProject().setDefaultIdentityMapSize(defaultSize);
}
String defaultSharedString = (String)sharedMap.remove(PersistenceUnitProperties.DEFAULT);
if (defaultSharedString != null) {
boolean defaultShared = Boolean.parseBoolean(defaultSharedString);
session.getProject().setDefaultCacheIsolation(defaultShared
? CacheIsolationType.SHARED : CacheIsolationType.ISOLATED);
}
Iterator it = session.getDescriptors().values().iterator();
while (it.hasNext() && (!typeMap.isEmpty() || !sizeMap.isEmpty() || !sharedMap.isEmpty())) {
ClassDescriptor descriptor = (ClassDescriptor)it.next();
if (descriptor.isDescriptorTypeAggregate()) {
continue;
}
String entityName = descriptor.getAlias();
String className = descriptor.getJavaClass().getName();
String name;
name = entityName;
String typeName = (String)typeMap.remove(name);
if( typeName == null) {
name = className;
typeName = (String)typeMap.remove(name);
}
if (typeName != null) {
Class type = findClassForProperty(typeName, PersistenceUnitProperties.CACHE_TYPE_ + name, getClass().getClassLoader());
descriptor.setIdentityMapClass(type);
}
name = entityName;
String sizeString = (String)sizeMap.remove(name);
if (sizeString == null) {
name = className;
sizeString = (String)sizeMap.remove(name);
}
if (sizeString != null) {
value = sizeString;
int size = Integer.parseInt(sizeString);
descriptor.setIdentityMapSize(size);
}
name = entityName;
String sharedString = (String)sharedMap.remove(name);
if (sharedString == null) {
name = className;
sharedString = (String)sharedMap.remove(name);
}
if (sharedString != null) {
boolean shared = Boolean.parseBoolean(sharedString);
descriptor.setCacheIsolation(shared ? CacheIsolationType.SHARED : CacheIsolationType.ISOLATED);
}
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(value, PersistenceUnitProperties.CACHE_SIZE_, exception));
}
}
/**
* Process all properties under "eclipselink.connection-pool.".
* This allows for named connection pools.
* It also processes "read", "write", "default" and "sequence" connection pools.
*/
protected void updateConnectionSettings(ServerSession serverSession, Map properties) {
Map connectionsMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CONNECTION_POOL, properties, serverSession);
if (connectionsMap.isEmpty()) {
return;
}
for (Map.Entry entry : connectionsMap.entrySet()) {
String poolName = "default";
String attribute = null;
try {
int dotIdx = entry.getKey().indexOf('.');
if (dotIdx == -1) {
attribute = entry.getKey();
} else {
String key = entry.getKey();
poolName = key.substring(0, dotIdx);
attribute = key.substring(dotIdx + 1, key.length());
}
ConnectionPool pool = null;
if (poolName.equals("write")) {
poolName = "default";
}
if (poolName.equals("read")) {
pool = serverSession.getReadConnectionPool();
// By default there is no connection pool, so if the default, create a new one.
if ((pool == null) || (pool == serverSession.getDefaultConnectionPool())) {
if (this.session.getDatasourceLogin().shouldUseExternalConnectionPooling()) {
pool = new ExternalConnectionPool(poolName, serverSession.getDatasourceLogin(), serverSession);
} else {
pool = new ConnectionPool(poolName, serverSession.getDatasourceLogin(), serverSession);
}
serverSession.setReadConnectionPool(pool);
}
} else if (poolName.equals("sequence")) {
pool = getDatabaseSession().getSequencingControl().getConnectionPool();
if (pool == null) {
if (this.session.getDatasourceLogin().shouldUseExternalConnectionPooling()) {
pool = new ExternalConnectionPool(poolName, serverSession.getDatasourceLogin(), serverSession);
} else {
pool = new ConnectionPool(poolName, serverSession.getDatasourceLogin(), serverSession);
}
getDatabaseSession().getSequencingControl().setConnectionPool(pool);
}
} else {
pool = serverSession.getConnectionPool(poolName);
if (pool == null) {
if (this.session.getDatasourceLogin().shouldUseExternalConnectionPooling()) {
pool = new ExternalConnectionPool(poolName, serverSession.getDatasourceLogin(), serverSession);
} else {
pool = new ConnectionPool(poolName, serverSession.getDatasourceLogin(), serverSession);
}
serverSession.addConnectionPool(pool);
}
}
if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_INITIAL)) {
pool.setInitialNumberOfConnections(Integer.parseInt((String)entry.getValue()));
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_MIN)) {
pool.setMinNumberOfConnections(Integer.parseInt((String)entry.getValue()));
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_MAX)) {
pool.setMaxNumberOfConnections(Integer.parseInt((String)entry.getValue()));
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_URL)) {
pool.setLogin(pool.getLogin().clone());
((DatabaseLogin)pool.getLogin()).setURL((String)entry.getValue());
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_NON_JTA_DATA_SOURCE)) {
pool.setLogin(pool.getLogin().clone());
((DatabaseLogin)pool.getLogin()).useDataSource((String)entry.getValue());
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_JTA_DATA_SOURCE)) {
pool.setLogin(pool.getLogin().clone());
((DatabaseLogin)pool.getLogin()).useDataSource((String)entry.getValue());
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_USER)) {
pool.setLogin(pool.getLogin().clone());
pool.getLogin().setUserName((String)entry.getValue());
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_PASSWORD)) {
pool.setLogin(pool.getLogin().clone());
pool.getLogin().setPassword((String)entry.getValue());
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_WAIT)) {
pool.setWaitTimeout(Integer.parseInt((String)entry.getValue()));
} else if (attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_FAILOVER)) {
String failoverPools = (String)entry.getValue();
if ((failoverPools.indexOf(',') != -1) || (failoverPools.indexOf(' ') != -1)) {
StringTokenizer tokenizer = new StringTokenizer(failoverPools, " ,");
while (tokenizer.hasMoreTokens()) {
pool.addFailoverConnectionPool(tokenizer.nextToken());
}
} else {
pool.addFailoverConnectionPool((String)entry.getValue());
}
} else if (poolName.equals("read") && attribute.equals(PersistenceUnitProperties.CONNECTION_POOL_SHARED)) {
boolean shared = Boolean.parseBoolean((String)entry.getValue());
if (shared) {
ReadConnectionPool readPool = new ReadConnectionPool(poolName, serverSession.getDatasourceLogin(), serverSession);
readPool.setInitialNumberOfConnections(pool.getInitialNumberOfConnections());
readPool.setMinNumberOfConnections(pool.getMinNumberOfConnections());
readPool.setMaxNumberOfConnections(pool.getMaxNumberOfConnections());
readPool.setWaitTimeout(pool.getWaitTimeout());
readPool.setLogin(pool.getLogin());
serverSession.setReadConnectionPool(readPool);
}
}
} catch (RuntimeException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(entry.getValue(), entry.getKey(), exception));
}
}
}
protected void updateConnectionPolicy(ServerSession serverSession, Map m) {
String isLazyString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.EXCLUSIVE_CONNECTION_IS_LAZY, m, session);
if(isLazyString != null) {
serverSession.getDefaultConnectionPolicy().setIsLazy(Boolean.parseBoolean(isLazyString));
}
ConnectionPolicy.ExclusiveMode exclusiveMode = getConnectionPolicyExclusiveModeFromProperties(m, session, true);
if(exclusiveMode != null) {
serverSession.getDefaultConnectionPolicy().setExclusiveMode(exclusiveMode);
}
}
public static ConnectionPolicy.ExclusiveMode getConnectionPolicyExclusiveModeFromProperties(Map m, AbstractSession abstractSession, boolean useSystemAsDefault) {
String exclusiveConnectionModeString = PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.EXCLUSIVE_CONNECTION_MODE, m, abstractSession, useSystemAsDefault);
if(exclusiveConnectionModeString != null) {
if(exclusiveConnectionModeString == ExclusiveConnectionMode.Isolated) {
return ConnectionPolicy.ExclusiveMode.Isolated;
} else if(exclusiveConnectionModeString == ExclusiveConnectionMode.Always) {
return ConnectionPolicy.ExclusiveMode.Always;
} else {
return ConnectionPolicy.ExclusiveMode.Transactional;
}
} else {
return null;
}
}
/**
* Perform any steps necessary prior to actual deployment. This includes any steps in the session
* creation that do not require the real loaded domain classes.
*
* The first call to this method caches persistenceUnitInfo which is reused in the following calls.
*
* Note that in JSE case factoryCount is NOT incremented on the very first call
* (by JavaSECMPInitializer.callPredeploy, typically in preMain).
* That provides 1 to 1 correspondence between factoryCount and the number of open factories.
*
* In case factoryCount > 0 the method just increments factoryCount.
* factory == 0 triggers creation of a new session.
*
* This method and undeploy - the only methods altering factoryCount - should be synchronized.
*
* @return A transformer (which may be null) that should be plugged into the proper
* classloader to allow classes to be transformed as they get loaded.
* @see #deploy(ClassLoader, Map)
*/
public synchronized ClassTransformer predeploy(PersistenceUnitInfo info, Map extendedProperties) {
ClassLoader classLoaderToUse = null;
// session == null
if (state == STATE_DEPLOY_FAILED || state == STATE_UNDEPLOYED) {
throw new PersistenceException(EntityManagerSetupException.cannotPredeploy(persistenceUnitInfo.getPersistenceUnitName(), state, persistenceException));
}
// session != null
if (state == STATE_PREDEPLOYED || state == STATE_DEPLOYED || state == STATE_HALF_DEPLOYED) {
session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_begin", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state, factoryCount});
factoryCount++;
session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state, factoryCount});
return null;
// session == null
} else if (state == STATE_INITIAL) {
persistenceUnitInfo = info;
if (!isCompositeMember()) {
if (mustBeCompositeMember(persistenceUnitInfo)) {
if (this.staticWeaveInfo == null) {
return null;
} else {
// predeploy is used for static weaving
throw new PersistenceException(EntityManagerSetupException.compositeMemberCannotBeUsedStandalone(persistenceUnitInfo.getPersistenceUnitName()));
}
}
}
}
// state is INITIAL or PREDEPLOY_FAILED or STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER, session == null
try {
// properties not used in STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER
Map predeployProperties = null;
// composite can't be in STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER
boolean isComposite = false;
if(state != STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER) {
//set the claasloader early on and change it if needed
classLoaderToUse = persistenceUnitInfo.getClassLoader();
predeployProperties = mergeMaps(extendedProperties, persistenceUnitInfo.getProperties());
// Translate old properties.
// This should be done before using properties (i.e. ServerPlatform).
translateOldProperties(predeployProperties, null);
String sessionsXMLStr = (String)predeployProperties.get(PersistenceUnitProperties.SESSIONS_XML);
if (sessionsXMLStr != null) {
isSessionLoadedFromSessionsXML = true;
}
// Create session (it needs to be done before initializing ServerPlatform and logging).
// If a sessions-xml is used this will get replaced later, but is required for logging.
isComposite = isComposite(persistenceUnitInfo);
if (isComposite) {
if (isSessionLoadedFromSessionsXML) {
throw EntityManagerSetupException.compositeIncompatibleWithSessionsXml(persistenceUnitInfo.getPersistenceUnitName());
}
session = new SessionBroker();
((SessionBroker)session).setShouldUseDescriptorAliases(true);
} else {
session = new ServerSession(new Project(new DatabaseLogin()));
//set the listener to process RCM metadata refresh commands
session.setRefreshMetadataListener(this);
}
session.setName(this.sessionName);
updateTunerPreDeploy(predeployProperties, classLoaderToUse);
updateTolerateInvalidJPQL(predeployProperties);
if (this.compositeEmSetupImpl == null) {
// session name and ServerPlatform must be set prior to setting the loggers.
if (this.staticWeaveInfo == null) {
updateServerPlatform(predeployProperties, classLoaderToUse);
// Update loggers and settings for the singleton logger and the session logger.
updateLoggers(predeployProperties, true, classLoaderToUse);
// log the server platform being used by the session
if (session.getSessionLog().shouldLog(SessionLog.FINE)) {
session.getSessionLog().log(SessionLog.FINE, SessionLog.SERVER,
"configured_server_platform", session.getServerPlatform().getClass().getName()); // NOI18N
}
// Get the temporary classLoader based on the platform
//Update performance profiler
updateProfiler(predeployProperties, classLoaderToUse);
} else {
// predeploy is used for static weaving
Writer writer = this.staticWeaveInfo.getLogWriter();
if (writer != null) {
session.getSessionLog().setWriter(writer);
}
session.setLogLevel(this.staticWeaveInfo.getLogLevel());
}
} else {
// composite member
session.setSessionLog(this.compositeEmSetupImpl.session.getSessionLog());
session.setProfiler(this.compositeEmSetupImpl.session.getProfiler());
}
// Cannot start logging until session and log and initialized, so log start of predeploy here.
session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_begin", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state, factoryCount});
//Project Cache accessor processing
updateProjectCache(predeployProperties, classLoaderToUse);
if (projectCacheAccessor!=null) {
//get the project from the cache
Project project = projectCacheAccessor.retrieveProject(predeployProperties, classLoaderToUse, session.getSessionLog());
if (project!=null) {
try {
DatabaseSessionImpl tempSession = (DatabaseSessionImpl)project.createServerSession();
tempSession.setName(this.sessionName);
tempSession.setSessionLog(session.getSessionLog());
tempSession.getSessionLog().setSession(tempSession);
if (this.staticWeaveInfo != null) {
tempSession.setLogLevel(this.staticWeaveInfo.getLogLevel());
}
tempSession.setProfiler(session.getProfiler());
tempSession.setRefreshMetadataListener(this);
session = tempSession;
// reusing the serverPlatform from the existing session would have been preferred,
// but its session is only set through the ServerPlatform constructor.
updateServerPlatform(predeployProperties, classLoaderToUse);
shouldBuildProject = false;
} catch (Exception e) {
//need a better exception here
throw new PersistenceException(e);
}
}
}
if (isSessionLoadedFromSessionsXML) {
if (this.compositeEmSetupImpl == null && this.staticWeaveInfo == null) {
JPAClassLoaderHolder privateClassLoaderHolder = session.getServerPlatform().getNewTempClassLoader(persistenceUnitInfo);
classLoaderToUse = privateClassLoaderHolder.getClassLoader();
} else {
classLoaderToUse = persistenceUnitInfo.getNewTempClassLoader();
}
// Loading session from sessions-xml.
String tempSessionName = sessionName;
if (isCompositeMember()) {
// composite member session name is always the same as puName
// need the session name specified in properties to read correct session from sessions.xml
tempSessionName = (String)predeployProperties.get(PersistenceUnitProperties.SESSION_NAME);
}
session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "loading_session_xml", sessionsXMLStr, tempSessionName);
if (tempSessionName == null) {
throw EntityManagerSetupException.sessionNameNeedBeSpecified(persistenceUnitInfo.getPersistenceUnitName(), sessionsXMLStr);
}
XMLSessionConfigLoader xmlLoader = new XMLSessionConfigLoader(sessionsXMLStr);
// Do not register the session with the SessionManager at this point, create temporary session using a local SessionManager and private class loader.
// This allows for the project to be accessed without loading any of the classes to allow weaving.
// Note that this method assigns sessionName to session.
Session tempSession = new SessionManager().getSession(xmlLoader, tempSessionName, classLoaderToUse, false, false);
// Load path of sessions-xml resource before throwing error so user knows which sessions-xml file was found (may be multiple).
session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "sessions_xml_path_where_session_load_from", xmlLoader.getSessionName(), xmlLoader.getResourcePath());
if (tempSession == null) {
throw ValidationException.noSessionFound(sessionName, sessionsXMLStr);
}
// Currently the session must be either a ServerSession or a SessionBroker, cannot be just a DatabaseSessionImpl.
if (tempSession.isServerSession() || tempSession.isSessionBroker()) {
session = (DatabaseSessionImpl) tempSession;
if (tempSessionName != sessionName) {
// set back the original session name
session.setName(sessionName);
}
} else {
throw EntityManagerSetupException.sessionLoadedFromSessionsXMLMustBeServerSession(persistenceUnitInfo.getPersistenceUnitName(), (String)predeployProperties.get(PersistenceUnitProperties.SESSIONS_XML), tempSession);
}
if (this.staticWeaveInfo == null) {
// Must now reset logging and server-platform on the loaded session.
// ServerPlatform must be set prior to setting the loggers.
updateServerPlatform(predeployProperties, classLoaderToUse);
// Update loggers and settings for the singleton logger and the session logger.
updateLoggers(predeployProperties, true, classLoaderToUse);
}
} else {
classLoaderToUse = persistenceUnitInfo.getClassLoader();
}
warnOldProperties(predeployProperties, session);
session.getPlatform().setConversionManager(new JPAConversionManager());
if (this.staticWeaveInfo == null) {
if (!isComposite) {
PersistenceUnitTransactionType transactionType=null;
//bug 5867753: find and override the transaction type
String transTypeString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.TRANSACTION_TYPE, predeployProperties, session);
if (transTypeString != null && transTypeString.length() > 0) {
transactionType=PersistenceUnitTransactionType.valueOf(transTypeString);
} else if (persistenceUnitInfo!=null){
transactionType=persistenceUnitInfo.getTransactionType();
}
if (!isValidationOnly(predeployProperties, false) && persistenceUnitInfo != null && transactionType == PersistenceUnitTransactionType.JTA) {
if (predeployProperties.get(PersistenceUnitProperties.JTA_DATASOURCE) == null && persistenceUnitInfo.getJtaDataSource() == null) {
if (predeployProperties.get(PersistenceUnitProperties.SCHEMA_DATABASE_PRODUCT_NAME) == null ||
predeployProperties.get(PersistenceUnitProperties.SCHEMA_DATABASE_MAJOR_VERSION) == null ||
predeployProperties.get(PersistenceUnitProperties.SCHEMA_DATABASE_MINOR_VERSION) == null) {
throw EntityManagerSetupException.jtaPersistenceUnitInfoMissingJtaDataSource(persistenceUnitInfo.getPersistenceUnitName());
}
}
}
}
// this flag is used to disable work done as a result of the LAZY hint on OneToOne and ManyToOne mappings
if(state == STATE_INITIAL) {
if (compositeEmSetupImpl == null) {
if(null == enableWeaving) {
enableWeaving = Boolean.TRUE;
}
isWeavingStatic = false;
String weaving = getConfigPropertyAsString(PersistenceUnitProperties.WEAVING, predeployProperties);
if (weaving != null && weaving.equalsIgnoreCase("false")) {
enableWeaving = Boolean.FALSE;
}else if (weaving != null && weaving.equalsIgnoreCase("static")) {
isWeavingStatic = true;
}
} else {
// composite member
// no weaving for composite forces no weaving for members
if (!compositeEmSetupImpl.enableWeaving) {
enableWeaving = Boolean.FALSE;
} else {
if(null == enableWeaving) {
enableWeaving = Boolean.TRUE;
}
String weaving = getConfigPropertyAsString(PersistenceUnitProperties.WEAVING, predeployProperties);
if (weaving != null && weaving.equalsIgnoreCase("false")) {
enableWeaving = Boolean.FALSE;
}
}
// static weaving is dictated by composite
isWeavingStatic = compositeEmSetupImpl.isWeavingStatic;
}
}
if (compositeEmSetupImpl == null) {
throwExceptionOnFail = "true".equalsIgnoreCase(
EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.THROW_EXCEPTIONS, predeployProperties, "true", session));
} else {
// composite member
throwExceptionOnFail = compositeEmSetupImpl.throwExceptionOnFail;
}
} else {
// predeploy is used for static weaving
enableWeaving = Boolean.TRUE;
}
weaveChangeTracking = false;
weaveLazy = false;
weaveEager = false;
weaveFetchGroups = false;
weaveInternal = false;
weaveRest = false;
weaveMappedSuperClass = false;
if (enableWeaving) {
weaveChangeTracking = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_CHANGE_TRACKING, predeployProperties, "true", session));
weaveLazy = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_LAZY, predeployProperties, "true", session));
weaveEager = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_EAGER, predeployProperties, "false", session));
weaveFetchGroups = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_FETCHGROUPS, predeployProperties, "true", session));
weaveInternal = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_INTERNAL, predeployProperties, "true", session));
weaveRest = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_REST, predeployProperties, shouldWeaveRestByDefault(classLoaderToUse), session));
weaveMappedSuperClass = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_MAPPEDSUPERCLASS, predeployProperties, "true", session));
}
}
if (shouldBuildProject && !isSessionLoadedFromSessionsXML ) {
if (isComposite) {
predeployCompositeMembers(predeployProperties, classLoaderToUse);
} else {
MetadataProcessor compositeProcessor = null;
if (compositeEmSetupImpl == null) {
mode = PersistenceUnitProcessor.Mode.ALL;
} else {
// composite member
if (state != STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER) {
state = STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER;
mode = PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL;
}
compositeProcessor = compositeEmSetupImpl.processor;
}
if (mode == PersistenceUnitProcessor.Mode.ALL || mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL) {
boolean usesMultitenantSharedEmf = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, predeployProperties, "true", session));
boolean usesMultitenantSharedCache = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_SHARED_CACHE, predeployProperties, "false", session));
// Create an instance of MetadataProcessor for specified persistence unit info
processor = new MetadataProcessor(persistenceUnitInfo, session, classLoaderToUse, weaveLazy, weaveEager, weaveFetchGroups, usesMultitenantSharedEmf, usesMultitenantSharedCache, predeployProperties, compositeProcessor);
//need to use the real classloader to create the repository class
updateMetadataRepository(predeployProperties, classLoaderToUse);
//bug:299926 - Case insensitive table / column matching with native SQL queries
EntityManagerSetupImpl.updateCaseSensitivitySettings(predeployProperties, processor.getProject(), session);
}
// Set the shared cache mode to the jakarta.persistence.sharedCache.mode property value.
updateSharedCacheMode(predeployProperties);
// Process the Object/relational metadata from XML and annotations.
// If Java Security is enabled, surround this call with a doPrivileged block.
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
AccessController.doPrivileged(new PrivilegedAction() {
@Override
public Void run() {
PersistenceUnitProcessor.processORMetadata(processor, throwExceptionOnFail, mode);
return null;
}
});
} else {
PersistenceUnitProcessor.processORMetadata(processor, throwExceptionOnFail, mode);
}
if (mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL) {
mode = PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_MIDDLE;
session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state + " " + mode , factoryCount});
return null;
} else if (mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_MIDDLE) {
mode = PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_FINAL;
session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state + " " + mode , factoryCount});
return null;
}
// mode == PersistenceUnitProcessor.Mode.ALL || mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_FINAL
// clear mode and proceed
mode = null;
if (session.getIntegrityChecker().hasErrors()){
session.handleException(new IntegrityException(session.getIntegrityChecker()));
}
// The transformer is capable of altering domain classes to handle a LAZY hint for OneToOne mappings. It will only
// be returned if we we are mean to process these mappings
if (enableWeaving) {
// build a list of entities the persistence unit represented by this EntityManagerSetupImpl will use
Collection entities = PersistenceUnitProcessor.buildEntityList(processor, classLoaderToUse);
this.weaver = TransformerFactory.createTransformerAndModifyProject(session, entities, classLoaderToUse, weaveLazy, weaveChangeTracking, weaveFetchGroups, weaveInternal, weaveRest, weaveMappedSuperClass);
session.getProject().setClassNamesForWeaving(new ArrayList(processor.getProject().getWeavableClassNames()));
}
//moved from deployment:
processor.addNamedQueries();
processor.addStructConverterNames();
}
} else {
//This means this session is from sessions.xml or a cached project
// The transformer is capable of altering domain classes to handle a LAZY hint for OneToOne mappings. It will only
// be returned if we we are meant to process these mappings.
if (enableWeaving) {
Collection persistenceClasses = new ArrayList();
MetadataAsmFactory factory = new MetadataAsmFactory(new MetadataLogger(session), classLoaderToUse);
if (shouldBuildProject) {
// If deploying from a sessions-xml it is still desirable to allow the classes to be weaved.
// build a list of entities the persistence unit represented by this EntityManagerSetupImpl will use
for (Iterator iterator = session.getProject().getDescriptors().keySet().iterator(); iterator.hasNext(); ) {
persistenceClasses.add(factory.getMetadataClass(((Class)iterator.next()).getName()));
}
} else {
// build a list of entities the persistence unit represented by this EntityManagerSetupImpl will use
for (String className : session.getProject().getClassNamesForWeaving()) {
persistenceClasses.add(factory.getMetadataClass(className));
}
}
this.weaver = TransformerFactory.createTransformerAndModifyProject(session, persistenceClasses, classLoaderToUse, weaveLazy, weaveChangeTracking, weaveFetchGroups, weaveInternal, weaveRest, weaveMappedSuperClass);
}
}
// composite member never has a factory - it is predeployed by the composite.
if (!isCompositeMember()) {
// factoryCount is not incremented only in case of a first call to preDeploy
// in non-container mode: this call is not associated with a factory
// but rather done by JavaSECMPInitializer.callPredeploy (typically in preMain).
if(state != STATE_INITIAL || this.isInContainerMode()) {
factoryCount++;
}
preInitializeMetamodel();
}
state = STATE_PREDEPLOYED;
session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state, factoryCount});
//gf3146: if static weaving is used, we should not return a transformer. Transformer should still be created though as it modifies descriptors
if (isWeavingStatic) {
return null;
} else {
return this.weaver;
}
} catch (Throwable ex) {
state = STATE_PREDEPLOY_FAILED;
// cache this.persistenceException before slow logging
PersistenceException persistenceEx = createPredeployFailedPersistenceException(ex);
// If session exists, use it for logging
if (session != null) {
session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state, factoryCount});
// If at least staticWeaveInfo exists, use it for logging
} else if (staticWeaveInfo != null && staticWeaveInfo.getLogLevel() <= SessionLog.FINEST) {
Writer logWriter = staticWeaveInfo.getLogWriter();
if (logWriter != null) {
String message = LoggingLocalization.buildMessage("predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), "N/A", state, factoryCount});
try {
logWriter.write(message);
logWriter.write(Helper.cr());
} catch (IOException ioex) {
// Ignore IOException
}
}
}
session = null;
mode = null;
throw persistenceEx;
}
}
protected PersistenceException createPredeployFailedPersistenceException(Throwable ex) {
PersistenceException perEx = new PersistenceException(EntityManagerSetupException.predeployFailed(persistenceUnitInfo.getPersistenceUnitName(), ex));
if (persistenceException == null) {
persistenceException = perEx;
}
return perEx;
}
/**
* Return the name of the session this SetupImpl is building. The session name is only known at deploy
* time and if this method is called prior to that, this method will return null.
*/
public String getDeployedSessionName(){
return session != null ? session.getName() : null;
}
public PersistenceUnitInfo getPersistenceUnitInfo(){
return persistenceUnitInfo;
}
public boolean isValidationOnly(Map m) {
return isValidationOnly(m, true);
}
protected boolean isValidationOnly(Map m, boolean shouldMergeMap) {
if (shouldMergeMap) {
m = mergeWithExistingMap(m);
}
String validationOnlyString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.VALIDATION_ONLY_PROPERTY, m, session);
if (validationOnlyString != null) {
return Boolean.parseBoolean(validationOnlyString);
} else {
return false;
}
}
/**
* Return if the session should be deployed and connected during the creation of the EntityManagerFactory,
* or if it should be deferred until createEntityManager().
* The default is to defer, but is only validating, or can be configured to deploy upfront to avoid hanging the
* application at runtime.
*/
public boolean shouldGetSessionOnCreateFactory(Map m) {
m = mergeWithExistingMap(m);
if (isValidationOnly(m, false)) {
return true;
}
String deployString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.DEPLOY_ON_STARTUP, m, this.session);
if (deployString != null) {
return Boolean.parseBoolean(deployString);
} else {
// If DDL schame generation is turned on, we need to deploy.
return hasSchemaDatabaseGeneration(m) || hasSchemaScriptsGeneration(m);
}
}
protected Map mergeWithExistingMap(Map m) {
if(persistenceUnitInfo != null) {
return mergeMaps(m, persistenceUnitInfo.getProperties());
} else {
return m;
}
}
public boolean isInContainerMode(){
return isInContainerMode;
}
/**
* Configure cache coordination using properties.
*/
protected void updateCacheCoordination(Map m, ClassLoader loader) {
String protocol = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_PROTOCOL, m, this.session);
String value = "";
String property = "";
try {
if (protocol != null) {
RemoteCommandManager rcm = new RemoteCommandManager(this.session);
if (protocol.equalsIgnoreCase(CacheCoordinationProtocol.JGROUPS)) {
property = PersistenceUnitProperties.COORDINATION_PROTOCOL;
value = "org.eclipse.persistence.sessions.coordination.jgroups.JGroupsTransportManager";
// Avoid compile and runtime dependency.
Class transportClass = findClassForProperty(value, PersistenceUnitProperties.COORDINATION_PROTOCOL, loader);
TransportManager transport = (TransportManager)transportClass.getConstructor().newInstance();
rcm.setTransportManager(transport);
String config = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JGROUPS_CONFIG, m, this.session);
if (config != null) {
transport.setConfig(config);
}
} else if (protocol.equalsIgnoreCase(CacheCoordinationProtocol.JMS) || protocol.equalsIgnoreCase(CacheCoordinationProtocol.JMSPublishing)) {
JMSPublishingTransportManager transport = null;
if (protocol.equalsIgnoreCase(CacheCoordinationProtocol.JMS)) {
transport = new JMSTopicTransportManager(rcm);
} else {
transport = new JMSPublishingTransportManager(rcm);
}
rcm.setTransportManager(transport);
String host = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JMS_HOST, m, this.session);
if (host != null) {
transport.setTopicHostUrl(host);
}
String topic = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JMS_TOPIC, m, this.session);
if (topic != null) {
transport.setTopicName(topic);
}
String factory = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JMS_FACTORY, m, this.session);
if (factory != null) {
transport.setTopicConnectionFactoryName(factory);
}
String reuse_publisher = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JMS_REUSE_PUBLISHER, m, this.session);
if (reuse_publisher != null) {
transport.setShouldReuseJMSTopicPublisher(reuse_publisher.equalsIgnoreCase("true"));
}
} else if (protocol.equalsIgnoreCase(CacheCoordinationProtocol.RMI) || protocol.equalsIgnoreCase(CacheCoordinationProtocol.RMIIIOP)) {
if (protocol.equalsIgnoreCase(CacheCoordinationProtocol.RMIIIOP)) {
((RMITransportManager) rcm.getTransportManager()).setIsRMIOverIIOP(true);
}
// Default protocol.
String delay = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_RMI_ANNOUNCEMENT_DELAY, m, this.session);
property = PersistenceUnitProperties.COORDINATION_RMI_ANNOUNCEMENT_DELAY;
value = delay;
if (delay != null) {
rcm.getDiscoveryManager().setAnnouncementDelay(Integer.parseInt(delay));
}
String multicast = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_RMI_MULTICAST_GROUP, m, this.session);
if (multicast != null) {
rcm.getDiscoveryManager().setMulticastGroupAddress(multicast);
}
String port = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_RMI_MULTICAST_GROUP_PORT, m, this.session);
property = PersistenceUnitProperties.COORDINATION_RMI_MULTICAST_GROUP_PORT;
value = port;
if (port != null) {
rcm.getDiscoveryManager().setMulticastPort(Integer.parseInt(port));
}
String timeToLive = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_RMI_PACKET_TIME_TO_LIVE, m, this.session);
property = PersistenceUnitProperties.COORDINATION_RMI_PACKET_TIME_TO_LIVE;
value = timeToLive;
if (timeToLive != null) {
rcm.getDiscoveryManager().setPacketTimeToLive(Integer.parseInt(timeToLive));
}
String url = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_RMI_URL, m, this.session);
if (url != null) {
rcm.setUrl(url);
}
} else {
property = PersistenceUnitProperties.COORDINATION_PROTOCOL;
value = protocol;
Class transportClass = findClassForProperty(protocol, PersistenceUnitProperties.COORDINATION_PROTOCOL, loader);
rcm.setTransportManager((TransportManager)transportClass.getConstructor().newInstance());
}
String serializer = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_SERIALIZER, m, this.session);
if (serializer != null) {
property = PersistenceUnitProperties.COORDINATION_SERIALIZER;
value = serializer;
Class transportClass = findClassForProperty(serializer, PersistenceUnitProperties.COORDINATION_SERIALIZER, loader);
rcm.setSerializer((Serializer)transportClass.getConstructor().newInstance());
}
String naming = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_NAMING_SERVICE, m, this.session);
if (naming != null) {
if (naming.equalsIgnoreCase("jndi")) {
rcm.getTransportManager().setNamingServiceType(TransportManager.JNDI_NAMING_SERVICE);
} else if (naming.equalsIgnoreCase("rmi")) {
rcm.getTransportManager().setNamingServiceType(TransportManager.REGISTRY_NAMING_SERVICE);
}
}
String user = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JNDI_USER, m, this.session);
if (user != null) {
rcm.getTransportManager().setUserName(user);
}
String password = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JNDI_PASSWORD, m, this.session);
if (password != null) {
rcm.getTransportManager().setPassword(password);
}
String context = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_JNDI_CONTEXT, m, this.session);
if (context != null) {
rcm.getTransportManager().setInitialContextFactoryName(context);
}
String removeOnError = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_REMOVE_CONNECTION, m, this.session);
if (removeOnError != null) {
rcm.getTransportManager().setShouldRemoveConnectionOnError(removeOnError.equalsIgnoreCase("true"));
}
String asynch = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_ASYNCH, m, this.session);
if (asynch != null) {
rcm.setShouldPropagateAsynchronously(asynch.equalsIgnoreCase("true"));
}
String threadPoolSize = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_THREAD_POOL_SIZE, m, this.session);
property = PersistenceUnitProperties.COORDINATION_THREAD_POOL_SIZE;
value = threadPoolSize;
if (threadPoolSize != null) {
this.session.getServerPlatform().setThreadPoolSize(Integer.parseInt(threadPoolSize));
}
String channel = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.COORDINATION_CHANNEL, m, this.session);
if (channel != null) {
rcm.setChannel(channel);
}
this.session.setCommandManager(rcm);
this.session.setShouldPropagateChanges(true);
}
} catch (ReflectiveOperationException | NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(value, property, exception));
}
}
/**
* Update session serializer.
*/
protected void updateSerializer(Map m, ClassLoader loader) {
String serializer = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.SERIALIZER, m, this.session);
if (serializer != null) {
if (serializer.length() > 0) {
try {
Class transportClass = findClassForProperty(serializer, PersistenceUnitProperties.SERIALIZER, loader);
this.session.setSerializer((Serializer)transportClass.getConstructor().newInstance());
} catch (Exception exception) {
this.session.handleException(ValidationException.invalidValueForProperty(serializer, PersistenceUnitProperties.SERIALIZER, exception));
}
} else {
this.session.setSerializer(JavaSerializer.instance);
}
}
}
/**
* Update whether session ShouldOptimizeResultSetAccess.
*/
protected void updateShouldOptimizeResultSetAccess(Map m) {
String resultSetAccessOptimization = PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.JDBC_RESULT_SET_ACCESS_OPTIMIZATION, m, this.session);
if (resultSetAccessOptimization != null) {
this.session.setShouldOptimizeResultSetAccess(resultSetAccessOptimization.equals("true"));
}
}
/**
* Update whether session should use externally defined multi tenancy.
*/
protected void updateTenancy(Map m, ClassLoader loader) {
String tenantStrategy = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_STRATEGY, m, this.session);
if(tenantStrategy != null) {
if ("external".equalsIgnoreCase(tenantStrategy)) {
SchemaPerMultitenantPolicy policy = new SchemaPerMultitenantPolicy();
String prop = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, m, session);
if (prop != null) {
policy.setShouldUseSharedEMF(Boolean.valueOf(prop));
}
prop = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_SHARED_CACHE, m, session);
if (prop != null) {
policy.setShouldUseSharedCache(Boolean.valueOf(prop));
}
session.getProject().setMultitenantPolicy(policy);
} else {
//assume it is a class with default constructor implementing existing interface
Class cls = findClassForProperty(tenantStrategy, PersistenceUnitProperties.MULTITENANT_STRATEGY, loader);
MultitenantPolicy policy = null;
try {
Constructor constructor = cls.getConstructor();
policy = (MultitenantPolicy) constructor.newInstance();
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw EntityManagerSetupException.failedToInstantiateProperty(tenantStrategy, PersistenceUnitProperties.MULTITENANT_STRATEGY, ex);
}
session.getProject().setMultitenantPolicy(policy);
}
}
}
/**
* Update whether session should tolerate invalid JPQL at creation time.
*/
protected void updateTolerateInvalidJPQL(Map m) {
String config =
PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.JPQL_TOLERATE, m, this.session);
// Tolerate invalid JPQL is ignored if running in validation only mode
if (config != null && isValidationOnly(m) == false) {
this.session.setTolerateInvalidJPQL(config.equals("true"));
}
}
/**
* Override the default login creation method.
* If persistenceInfo is available, use the information from it to setup the login
* and possibly to set readConnectionPool.
*/
protected void updateLogins(Map m){
DatasourceLogin login = (DatasourceLogin)this.session.getDatasourceLogin();
String eclipselinkPlatform = PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.TARGET_DATABASE, m, this.session);
if (eclipselinkPlatform != null) {
login.setPlatformClassName(eclipselinkPlatform, this.persistenceUnitInfo.getClassLoader());
}
// Check for EIS platform, need to use an EIS login.
boolean isEIS = false;
if (login.getDatasourcePlatform() instanceof EISPlatform) {
isEIS = true;
EISLogin newLogin = new EISLogin();
newLogin.setDatasourcePlatform(login.getDatasourcePlatform());
this.session.setDatasourceLogin(newLogin);
if (this.session.isServerSession()) {
for (ConnectionPool pool : ((ServerSession)this.session).getConnectionPools().values()) {
pool.setLogin(newLogin);
}
}
login = newLogin;
}
// Check for EIS or custom (JDBC) Connector class.
Object connectorValue = getConfigPropertyLogDebug(PersistenceUnitProperties.NOSQL_CONNECTION_SPEC, m, this.session);
String connectorProperty = PersistenceUnitProperties.NOSQL_CONNECTION_SPEC;
if (connectorValue == null) {
connectorValue = getConfigPropertyLogDebug(PersistenceUnitProperties.JDBC_CONNECTOR, m, this.session);
connectorProperty = PersistenceUnitProperties.JDBC_CONNECTOR;
}
if (connectorValue instanceof Connector) {
login.setConnector((Connector)connectorValue);
} else if (connectorValue instanceof String) {
Class cls = null;
// Try both class loaders.
try {
cls = findClassForProperty((String)connectorValue, connectorProperty, this.persistenceUnitInfo.getClassLoader());
} catch (Throwable failed) {
cls = findClassForProperty((String)connectorValue, connectorProperty, getClass().getClassLoader());
}
Connector connector = null;
try {
Constructor constructor = cls.getConstructor();
connector = (Connector)constructor.newInstance();
} catch (Exception exception) {
throw EntityManagerSetupException.failedToInstantiateProperty((String)connectorValue, connectorProperty, exception);
}
if (connector != null) {
login.setConnector(connector);
}
} else if (connectorValue != null) {
// Assume JCA connection spec.
((EISConnectionSpec)login.getConnector()).setConnectionSpecObject(connectorValue);
}
// Check for EIS ConnectionFactory.
Object factoryValue = getConfigPropertyLogDebug(PersistenceUnitProperties.NOSQL_CONNECTION_FACTORY, m, this.session);
if (factoryValue instanceof String) {
// JNDI name.
((EISConnectionSpec)login.getConnector()).setName((String)factoryValue);
} else if (factoryValue != null) {
((EISConnectionSpec)login.getConnector()).setConnectionFactoryObject(factoryValue);
}
// Process EIS or JDBC connection properties.
Map propertiesMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.NOSQL_PROPERTY, m, session);
if (propertiesMap.isEmpty()) {
propertiesMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.JDBC_PROPERTY, m, session);
}
for (Iterator iterator = propertiesMap.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry entry = (Map.Entry)iterator.next();
String property = (String)entry.getKey();
Object value = entry.getValue();
login.setProperty(property, value);
}
// Note: This call does not checked the stored persistenceUnitInfo or extended properties because
// the map passed into this method should represent the full set of properties we expect to process
String user = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_USER, m, this.session);
String password = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_PASSWORD, m, this.session);
if(user != null) {
login.setUserName(user);
}
if (password != null) {
login.setPassword(this.securableObjectHolder.getSecurableObject().decryptPassword(password));
}
PersistenceUnitTransactionType transactionType = this.persistenceUnitInfo.getTransactionType();
//bug 5867753: find and override the transaction type using properties
String transTypeString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.TRANSACTION_TYPE, m, this.session);
if (transTypeString != null && transTypeString.length() > 0) {
transactionType = PersistenceUnitTransactionType.valueOf(transTypeString);
}
//find the jta datasource
javax.sql.DataSource jtaDatasource = getDatasourceFromProperties(m, PersistenceUnitProperties.JTA_DATASOURCE, this.persistenceUnitInfo.getJtaDataSource());
//find the non jta datasource
javax.sql.DataSource nonjtaDatasource = getDatasourceFromProperties(m, PersistenceUnitProperties.NON_JTA_DATASOURCE, this.persistenceUnitInfo.getNonJtaDataSource());
if (isValidationOnly(m, false) && transactionType == PersistenceUnitTransactionType.JTA && jtaDatasource == null) {
updateLoginDefaultConnector(login, m);
return;
}
login.setUsesExternalTransactionController(transactionType == PersistenceUnitTransactionType.JTA);
// Avoid processing data-source if EIS, as container may pass in a default one.
if (isEIS) {
return;
}
javax.sql.DataSource mainDatasource = null;
javax.sql.DataSource readDatasource = null;
if (login.shouldUseExternalTransactionController()) {
// JtaDataSource is guaranteed to be non null - otherwise exception would've been thrown earlier
mainDatasource = jtaDatasource;
// only define readDatasource if there is jta mainDatasource
readDatasource = nonjtaDatasource;
} else {
// JtaDataSource will be ignored because transactionType is RESOURCE_LOCAL
if (jtaDatasource != null) {
session.log(SessionLog.WARNING, SessionLog.TRANSACTION, "resource_local_persistence_init_info_ignores_jta_data_source", this.persistenceUnitInfo.getPersistenceUnitName());
}
if (nonjtaDatasource != null) {
mainDatasource = nonjtaDatasource;
} else {
updateLoginDefaultConnector(login, m);
return;
}
}
// mainDatasource is guaranteed to be non null - TODO: No it is not, if they did not set one it is null, should raise error, not null-pointer.
if (!(login.getConnector() instanceof JNDIConnector)) {
JNDIConnector jndiConnector;
if (mainDatasource instanceof DataSourceImpl) {
//Bug5209363 Pass in the datasource name instead of the dummy datasource
jndiConnector = new JNDIConnector(((DataSourceImpl)mainDatasource).getName());
} else {
jndiConnector = new JNDIConnector(mainDatasource);
}
login.setConnector(jndiConnector);
String useInternalConnectionPool = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONNECTION_POOL_INTERNALLY_POOL_DATASOURCE, m, this.session);
if (!"true".equalsIgnoreCase(useInternalConnectionPool)){
login.setUsesExternalConnectionPooling(true);
}
}
if (this.session.isServerSession()) {
// set readLogin
if (readDatasource != null) {
DatasourceLogin readLogin = login.clone();
readLogin.dontUseExternalTransactionController();
JNDIConnector jndiConnector;
if (readDatasource instanceof DataSourceImpl) {
//Bug5209363 Pass in the datasource name instead of the dummy datasource
jndiConnector = new JNDIConnector(((DataSourceImpl)readDatasource).getName());
} else {
jndiConnector = new JNDIConnector(readDatasource);
}
readLogin.setConnector(jndiConnector);
((ServerSession)this.session).setReadConnectionPool(readLogin);
}
}
}
/**
* This is used to return either the defaultDatasource or, if one exists, a datasource
* defined under the property from the Map m. This method will build a DataSourceImpl
* object to hold the url if the property in Map m defines a string instead of a datasource.
*/
protected javax.sql.DataSource getDatasourceFromProperties(Map m, String property, javax.sql.DataSource defaultDataSource){
Object datasource = getConfigPropertyLogDebug(property, m, session);
if ( datasource == null ){
return defaultDataSource;
}
if ( datasource instanceof String){
if(((String)datasource).length() > 0) {
// Create a dummy DataSource that will throw an exception on access
return new DataSourceImpl((String)datasource, null, null, null);
} else {
// allow an empty string data source property passed to createEMF to cancel data source specified in persistence.xml
return null;
}
}
if ( !(datasource instanceof javax.sql.DataSource) ){
//A warning should be enough. Though an error might be better, the properties passed in could contain anything
session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "invalid_datasource_property_value", property, datasource);
return defaultDataSource;
}
return (javax.sql.DataSource)datasource;
}
/**
* In cases where there is no data source, we will use properties to configure the login for
* our session. This method gets those properties and sets them on the login.
*/
protected void updateLoginDefaultConnector(DatasourceLogin login, Map m){
//Login info might be already set with sessions.xml and could be overridden by session customizer after this
//If login has default connector then JDBC properties update(override) the login info
if ((login.getConnector() instanceof DefaultConnector)) {
DatabaseLogin dbLogin = (DatabaseLogin)login;
// Note: This call does not checked the stored persistenceUnitInfo or extended properties because
// the map passed into this method should represent the full set of properties we expect to process
String jdbcDriver = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_DRIVER, m, session);
String connectionString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_URL, m, session);
if(connectionString != null) {
dbLogin.setConnectionString(connectionString);
}
if(jdbcDriver != null) {
dbLogin.setDriverClassName(jdbcDriver);
}
}
}
/**
* Configure the internal connection pooling parameters.
* By default if nothing is configured a default shared (exclusive) read/write pool is used with 32 min/max connections and 1 initial.
*/
@SuppressWarnings("deprecation")
protected void updatePools(ServerSession serverSession, Map m) {
String value = null;
String property = null;
try {
// Configure default/write connection pool.
// Sizes are irrelevant for external connection pool
if (!serverSession.getDefaultConnectionPool().getLogin().shouldUseExternalConnectionPooling()) {
// CONNECTION and WRITE_CONNECTION properties both configure the default pool (mean the same thing, but WRITE normally used with READ).
property = PersistenceUnitProperties.JDBC_CONNECTIONS_MIN;
value = getConfigPropertyAsStringLogDebug(property, m, serverSession);
if (value != null) {
serverSession.getDefaultConnectionPool().setMinNumberOfConnections(Integer.parseInt(value));
}
property = PersistenceUnitProperties.JDBC_CONNECTIONS_MAX;
value = getConfigPropertyAsStringLogDebug(property, m, serverSession);
if (value != null) {
serverSession.getDefaultConnectionPool().setMaxNumberOfConnections(Integer.parseInt(value));
}
property = PersistenceUnitProperties.JDBC_CONNECTIONS_INITIAL;
value = getConfigPropertyAsStringLogDebug(property, m, serverSession);
if (value != null) {
serverSession.getDefaultConnectionPool().setInitialNumberOfConnections(Integer.parseInt(value));
}
property = PersistenceUnitProperties.JDBC_WRITE_CONNECTIONS_MIN;
value = getConfigPropertyAsStringLogDebug(property, m, serverSession);
if (value != null) {
serverSession.getDefaultConnectionPool().setMinNumberOfConnections(Integer.parseInt(value));
}
property = PersistenceUnitProperties.JDBC_WRITE_CONNECTIONS_MAX;
value = getConfigPropertyAsStringLogDebug(property, m, serverSession);
if (value != null) {
serverSession.getDefaultConnectionPool().setMaxNumberOfConnections(Integer.parseInt(value));
}
property = PersistenceUnitProperties.JDBC_WRITE_CONNECTIONS_INITIAL;
value = getConfigPropertyAsStringLogDebug(property, m, serverSession);
if (value != null) {
serverSession.getDefaultConnectionPool().setInitialNumberOfConnections(Integer.parseInt(value));
}
}
// Configure read connection pool if set.
// Sizes and shared option are irrelevant for external connection pool
if (!serverSession.getReadConnectionPool().getLogin().shouldUseExternalConnectionPooling()) {
String shared = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_SHARED, m, serverSession);
boolean isShared = false;
if (shared != null) {
isShared = Boolean.parseBoolean(shared);
}
ConnectionPool pool = null;
if (isShared) {
pool = new ReadConnectionPool("read", serverSession.getReadConnectionPool().getLogin(), serverSession);
} else {
pool = new ConnectionPool("read", serverSession.getReadConnectionPool().getLogin(), serverSession);
}
String min = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MIN, m, serverSession);
if (min != null) {
value = min;
property = PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MIN;
pool.setMinNumberOfConnections(Integer.parseInt(min));
}
String max = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MAX, m, serverSession);
if (max != null) {
value = max;
property = PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MAX;
pool.setMaxNumberOfConnections(Integer.parseInt(max));
}
String initial = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_INITIAL, m, serverSession);
if (initial != null) {
value = initial;
property = PersistenceUnitProperties.JDBC_READ_CONNECTIONS_INITIAL;
pool.setInitialNumberOfConnections(Integer.parseInt(initial));
}
// Only set the read pool if they configured it, otherwise use default shared read/write.
if (isShared || (min != null) || (max != null) || (initial != null)) {
serverSession.setReadConnectionPool(pool);
}
String wait = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_CONNECTIONS_WAIT, m, serverSession);
if (wait != null) {
value = wait;
property = PersistenceUnitProperties.JDBC_CONNECTIONS_WAIT;
serverSession.getDefaultConnectionPool().setWaitTimeout(Integer.parseInt(wait));
pool.setWaitTimeout(Integer.parseInt(wait));
}
}
// Configure sequence connection pool if set.
String sequence = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL, m, serverSession);
if (sequence != null) {
serverSession.getSequencingControl().setShouldUseSeparateConnection(Boolean.parseBoolean(sequence));
}
String sequenceDataSource = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_DATASOURCE, m, serverSession);
if (sequenceDataSource != null) {
DatasourceLogin login = this.session.getLogin().clone();
login.dontUseExternalTransactionController();
JNDIConnector jndiConnector = new JNDIConnector(sequenceDataSource);
login.setConnector(jndiConnector);
serverSession.getSequencingControl().setLogin(login);
}
// Sizes and shared option are irrelevant for external connection pool
if (!serverSession.getReadConnectionPool().getLogin().shouldUseExternalConnectionPooling()) {
value = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MIN, m, serverSession);
if (value != null) {
property = PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MIN;
serverSession.getSequencingControl().setMinPoolSize(Integer.parseInt(value));
}
value = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MAX, m, serverSession);
if (value != null) {
property = PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MAX;
serverSession.getSequencingControl().setMaxPoolSize(Integer.parseInt(value));
}
value = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_INITIAL, m, serverSession);
if (value != null) {
property = PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_INITIAL;
serverSession.getSequencingControl().setInitialPoolSize(Integer.parseInt(value));
}
}
} catch (NumberFormatException exception) {
serverSession.handleException(ValidationException.invalidValueForProperty(value, property, exception));
}
}
/**
* Normally when a property is missing nothing should be applied to the session.
* However there are several session attributes that defaulted in EJB3 to the values
* different from EclipseLink defaults.
* This function applies defaults for such properties and registers the session.
* All other session-related properties are applied in updateServerSession.
* Note that updateSession may be called several times on the same session
* (before login), but initSession is called just once - before the first call
* to updateSession.
*/
protected void initSession() {
assignCMP3Policy();
if(!isCompositeMember()) {
// Register session that has been created earlier.
addSessionToGlobalSessionManager();
}
}
/**
* Make any changes to our ServerSession that can be made after it is created.
*/
protected void updateSession(Map m, ClassLoader loader) {
if (session == null || (session.isDatabaseSession() && ((DatabaseSessionImpl)session).isLoggedIn())) {
return;
}
// In deploy ServerPlatform could've changed which will affect the loggers.
boolean serverPlatformChanged = updateServerPlatform(m, loader);
updateJPQLParser(m);
if (!session.hasBroker()) {
updateLoggers(m, serverPlatformChanged, loader);
updateProfiler(m,loader);
}
// log the server platform being used by the session if it has been changed
if (serverPlatformChanged && session.getSessionLog().shouldLog(SessionLog.FINE)) {
session.getSessionLog().log(SessionLog.FINE, SessionLog.SERVER,
"configured_server_platform", session.getServerPlatform().getClass().getName()); // NOI18N
}
if(session.isBroker()) {
PersistenceUnitTransactionType transactionType = persistenceUnitInfo.getTransactionType();
//bug 5867753: find and override the transaction type using properties
String transTypeString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.TRANSACTION_TYPE, m, session);
if (transTypeString != null) {
transactionType = PersistenceUnitTransactionType.valueOf(transTypeString);
}
((DatasourceLogin)session.getDatasourceLogin()).setUsesExternalTransactionController(transactionType == PersistenceUnitTransactionType.JTA);
} else {
String shouldBindString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_BIND_PARAMETERS, m, session);
if (shouldBindString != null) {
session.getPlatform().setShouldBindAllParameters(Boolean.parseBoolean(shouldBindString));
}
String shouldForceBindString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_FORCE_BIND_PARAMETERS, m, session);
if(shouldForceBindString != null) {
session.getPlatform().setShouldForceBindAllParameters(Boolean.parseBoolean(shouldForceBindString));
}
String allowPartialBindString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_ALLOW_PARTIAL_PARAMETERS, m, session);
if(allowPartialBindString != null) {
session.getPlatform().setShouldBindPartialParameters(Boolean.parseBoolean(allowPartialBindString));
}
updateLogins(m);
}
if (!session.getDatasourceLogin().shouldUseExternalTransactionController()) {
session.getServerPlatform().disableJTA();
}
if(session.isServerSession()) {
updatePools((ServerSession)session, m);
updateConnectionSettings((ServerSession)session, m);
if (!isSessionLoadedFromSessionsXML) {
updateDescriptorCacheSettings(m, loader);
}
updateConnectionPolicy((ServerSession)session, m);
}
if(session.isBroker()) {
if (this.compositeMemberEmSetupImpls != null) {
// composite
Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, m);
for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) {
// the properties guaranteed to be non-null after updateCompositeMemberProperties call
String compositeMemberPuName = compositeMemberEmSetupImpl.getPersistenceUnitInfo().getPersistenceUnitName();
Map compositeMemberProperties = (Map)compositeMemberMapOfProperties.get(compositeMemberPuName);
// debug output added to make it easier to navigate the log because the method is called outside of composite member deploy
compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_begin_call", new Object[]{"updateSession", compositeMemberPuName, state});
compositeMemberEmSetupImpl.updateSession(compositeMemberProperties, loader);
compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_end_call", new Object[]{"updateSession", compositeMemberPuName, state});
}
}
setSessionEventListener(m, loader);
setExceptionHandler(m, loader);
updateAllowZeroIdSetting(m);
updateCacheCoordination(m, loader);
processSessionCustomizer(m, loader);
} else {
setSessionEventListener(m, loader);
setExceptionHandler(m, loader);
updateBatchWritingSetting(m, loader);
updateNativeSQLSetting(m);
updateSequencing(m);
updateSequencingStart(m);
updateAllowNativeSQLQueriesSetting(m);
updateSQLCastSetting(m);
updateUppercaseSetting(m);
updateCacheStatementSettings(m);
updateAllowExtendedCacheLogging(m);
updateAllowExtendedThreadLogging(m);
updateAllowExtendedThreadLoggingThreadDump(m);
updateTemporalMutableSetting(m);
updateTableCreationSettings(m);
updateIndexForeignKeys(m);
if (!session.hasBroker()) {
updateAllowZeroIdSetting(m);
}
updateIdValidation(m);
updatePessimisticLockTimeout(m);
updatePessimisticLockTimeoutUnit(m);
updateQueryTimeout(m);
updateQueryTimeoutUnit(m);
updateLockingTimestampDefault(m);
updateSQLCallDeferralDefault(m);
updateNamingIntoIndexed(m);
if (!session.hasBroker()) {
updateCacheCoordination(m, loader);
}
updatePartitioning(m, loader);
updateDatabaseEventListener(m, loader);
updateSerializer(m, loader);
updateShouldOptimizeResultSetAccess(m);
updateTolerateInvalidJPQL(m);
updateTenancy(m, loader);
// ConcurrencyManager properties
updateConcurrencyManagerWaitTime(m);
updateConcurrencyManagerBuildObjectCompleteWaitTime(m);
updateConcurrencyManagerMaxAllowedSleepTime(m);
updateConcurrencyManagerMaxAllowedFrequencyToProduceTinyDumpLogMessage(m);
updateConcurrencyManagerMaxAllowedFrequencyToProduceMassiveDumpLogMessage(m);
updateConcurrencyManagerAllowInterruptedExceptionFired(m);
updateConcurrencyManagerAllowConcurrencyExceptionToBeFiredUp(m);
updateConcurrencyManagerAllowTakingStackTraceDuringReadLockAcquisition(m);
updateConcurrencyManagerUseObjectBuildingSemaphore(m);
updateConcurrencyManagerUseWriteLockManagerSemaphore(m);
updateConcurrencyManagerNoOfThreadsAllowedToObjectBuildInParallel(m);
updateConcurrencyManagerNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel(m);
updateConcurrencySemaphoreMaxTimePermit(m);
updateConcurrencySemaphoreLogTimeout(m);
// Customizers should be processed last
processDescriptorCustomizers(m, loader);
processSessionCustomizer(m, loader);
setDescriptorNamedQueries(m);
}
}
/**
* This sets the isInContainerMode flag.
* "true" indicates container case, "false" - SE.
*/
public void setIsInContainerMode(boolean isInContainerMode) {
this.isInContainerMode = isInContainerMode;
}
/**
* Used to indicate that an EntityManagerFactoryImpl based on this
* EntityManagerSetupImpl has been refreshed. This means this EntityManagerSetupImpl
* will no longer be associated with new EntityManagerFactories
*/
public void setIsMetadataExpired(boolean hasExpiredMetadata) {
this.isMetadataExpired = hasExpiredMetadata;
}
protected void processSessionCustomizer(Map m, ClassLoader loader) {
SessionCustomizer sessionCustomizer;
Object customizer = getConfigPropertyLogDebug(PersistenceUnitProperties.SESSION_CUSTOMIZER, m, session);
if (customizer == null) {
return;
}
if (customizer instanceof String) {
Class sessionCustomizerClass = findClassForProperty((String) customizer, PersistenceUnitProperties.SESSION_CUSTOMIZER, loader);
try {
sessionCustomizer = (SessionCustomizer) sessionCustomizerClass.getConstructor().newInstance();
} catch (Exception ex) {
throw EntityManagerSetupException.failedWhileProcessingProperty(PersistenceUnitProperties.SESSION_CUSTOMIZER, (String) customizer, ex);
}
} else {
sessionCustomizer = (SessionCustomizer) customizer;
}
try {
sessionCustomizer.customize(session);
} catch (Exception ex) {
throw EntityManagerSetupException.failedWhileProcessingProperty(PersistenceUnitProperties.SESSION_CUSTOMIZER, customizer.toString(), ex);
}
}
protected void initOrUpdateLogging(Map m, SessionLog log) {
String logLevelString = PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.LOGGING_LEVEL, m, session);
if (logLevelString != null) {
log.setLevel(AbstractSessionLog.translateStringToLoggingLevel(logLevelString));
}
// category-specific logging level
Map categoryLogLevelMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CATEGORY_LOGGING_LEVEL_, m, session);
if(!categoryLogLevelMap.isEmpty()) {
Iterator it = categoryLogLevelMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String category = (String)entry.getKey();
String value = (String)entry.getValue();
log.setLevel(AbstractSessionLog.translateStringToLoggingLevel(value), category);
}
}
String tsString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.LOGGING_TIMESTAMP, m, session);
if (tsString != null) {
log.setShouldPrintDate(Boolean.parseBoolean(tsString));
}
String threadString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.LOGGING_THREAD, m, session);
if (threadString != null) {
log.setShouldPrintThread(Boolean.parseBoolean(threadString));
}
String sessionString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.LOGGING_SESSION, m, session);
if (sessionString != null) {
log.setShouldPrintSession(Boolean.parseBoolean(sessionString));
}
String connectionString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.LOGGING_CONNECTION, m, session);
if (connectionString != null) {
log.setShouldPrintConnection(Boolean.parseBoolean(connectionString));
}
String exString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.LOGGING_EXCEPTIONS, m, session);
if (exString != null) {
log.setShouldLogExceptionStackTrace(Boolean.parseBoolean(exString));
}
String shouldDisplayData = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.LOGGING_PARAMETERS, m, session);
if (shouldDisplayData != null) {
log.setShouldDisplayData(Boolean.parseBoolean(shouldDisplayData));
}
}
protected void processDescriptorCustomizers(Map m, ClassLoader loader) {
Map customizerMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.DESCRIPTOR_CUSTOMIZER_, m, session);
if (customizerMap.isEmpty()) {
return;
}
Iterator it = customizerMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = (Map.Entry)it.next();
String name = (String)entry.getKey();
String customizerClassName = (String)entry.getValue();
ClassDescriptor descriptor = session.getDescriptorForAlias(name);
if (descriptor == null) {
try {
Class javaClass = findClass(name, loader);
descriptor = session.getDescriptor(javaClass);
} catch (Exception ex) {
throw EntityManagerSetupException.failedWhileProcessingProperty(PersistenceUnitProperties.DESCRIPTOR_CUSTOMIZER_ + name, customizerClassName, ex);
}
}
if (descriptor != null) {
Class customizerClass = findClassForProperty(customizerClassName, PersistenceUnitProperties.DESCRIPTOR_CUSTOMIZER_ + name, loader);
try {
DescriptorCustomizer customizer = (DescriptorCustomizer)customizerClass.getConstructor().newInstance();
customizer.customize(descriptor);
} catch (Exception ex) {
throw EntityManagerSetupException.failedWhileProcessingProperty(PersistenceUnitProperties.DESCRIPTOR_CUSTOMIZER_ + name, customizerClassName, ex);
}
} else {
// TODO throw a better error, missing descriptor for property.
throw EntityManagerSetupException.failedWhileProcessingProperty(PersistenceUnitProperties.DESCRIPTOR_CUSTOMIZER_ + name, customizerClassName, null);
}
}
}
public boolean isInitial() {
return state == STATE_INITIAL;
}
/**
* Used to indicate that an EntityManagerFactoryImpl based on this
* EntityManagerSetupImpl has been refreshed. This means this EntityManagerSetupImpl
* will no longer be associated with new EntityManagerFactories
*/
public boolean isMetadataExpired() {
return isMetadataExpired;
}
public boolean isPredeployed() {
return state == STATE_PREDEPLOYED;
}
public boolean isDeployed() {
return state == STATE_DEPLOYED;
}
public boolean isHalfDeployed() {
return state == STATE_HALF_DEPLOYED;
}
public boolean isUndeployed() {
return state == STATE_UNDEPLOYED;
}
public boolean isPredeployFailed() {
return state == STATE_PREDEPLOY_FAILED;
}
public boolean isDeployFailed() {
return state == STATE_DEPLOY_FAILED;
}
public boolean isHalfPredeployedCompositeMember() {
return state == STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER;
}
public String getPersistenceUnitUniqueName() {
return this.persistenceUnitUniqueName;
}
public int getFactoryCount() {
return factoryCount;
}
public String getSessionName() {
return this.sessionName;
}
public boolean shouldRedeploy() {
return state == STATE_UNDEPLOYED || state == STATE_PREDEPLOY_FAILED;
}
/**
* Return if MetadataSource refresh commands should be sent when refresh is called
* Checks the PersistenceUnitProperties.METADATA_SOURCE_RCM_COMMAND property and defaults to true.
*/
public boolean shouldSendMetadataRefreshCommand(Map m) {
String sendCommand = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.METADATA_SOURCE_RCM_COMMAND, m, this.session);
if (sendCommand != null) {
return Boolean.parseBoolean(sendCommand);
} else {
return true;
}
}
/**
* Undeploy may be called several times, but only the call that decreases
* factoryCount to 0 disconnects the session and removes it from the session manager.
* This method and predeploy - the only methods altering factoryCount - should be synchronized.
* After undeploy call that turns factoryCount to 0:
* session==null;
* PREDEPLOYED, DEPLOYED and DEPLOYED_FAILED states change to UNDEPLOYED state.
*/
public synchronized void undeploy() {
if (state == STATE_INITIAL || state == STATE_PREDEPLOY_FAILED || state == STATE_UNDEPLOYED) {
// must already have factoryCount==0 and session==null
return;
}
// state is PREDEPLOYED, DEPLOYED or DEPLOY_FAILED
session.log(SessionLog.FINEST, SessionLog.JPA, "undeploy_begin", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state, factoryCount});
try {
factoryCount--;
if(factoryCount > 0) {
return;
}
synchronized (EntityManagerFactoryProvider.emSetupImpls) {
state = STATE_UNDEPLOYED;
removeSessionFromGlobalSessionManager();
// remove undeployed emSetupImpl from the map
EntityManagerSetupImpl emSetupImpl = EntityManagerFactoryProvider.emSetupImpls.get(sessionName);
if ((emSetupImpl != null) && (emSetupImpl.equals(this))) {
EntityManagerFactoryProvider.emSetupImpls.remove(sessionName);
}
}
} finally {
session.log(SessionLog.FINEST, SessionLog.JPA, "undeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state, factoryCount});
if(state == STATE_UNDEPLOYED) {
session = null;
}
}
}
/**
* INTERNAL:
* By default we require a connection to the database. However, when
* generating schema to scripts only, this is not required.
*/
public void setRequiresConnection(boolean requiresConnection) {
this.requiresConnection = requiresConnection;
}
/**
* Allow customized session event listener to be added into session.
* The method needs to be called in deploy stage.
*/
protected void setSessionEventListener(Map m, ClassLoader loader){
//Set event listener if it has been specified.
String sessionEventListenerClassName = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.SESSION_EVENT_LISTENER_CLASS, m, session);
if(sessionEventListenerClassName!=null){
Class sessionEventListenerClass = findClassForProperty(sessionEventListenerClassName,PersistenceUnitProperties.SESSION_EVENT_LISTENER_CLASS, loader);
try {
SessionEventListener sessionEventListener = (SessionEventListener)buildObjectForClass(sessionEventListenerClass, SessionEventListener.class);
if(sessionEventListener!=null){
session.getEventManager().addListener(sessionEventListener);
} else {
session.handleException(ValidationException.invalidSessionEventListenerClass(sessionEventListenerClassName));
}
} catch (IllegalAccessException e) {
session.handleException(ValidationException.cannotInstantiateSessionEventListenerClass(sessionEventListenerClassName,e));
} catch (PrivilegedActionException e) {
session.handleException(ValidationException.cannotInstantiateSessionEventListenerClass(sessionEventListenerClassName,e));
} catch (InstantiationException e) {
session.handleException(ValidationException.cannotInstantiateSessionEventListenerClass(sessionEventListenerClassName,e));
}
}
}
/**
* Allow customized exception handler to be added into session.
* The method needs to be called in deploy and pre-deploy stage.
*/
protected void setExceptionHandler(Map m, ClassLoader loader){
//Set exception handler if it was specified.
String exceptionHandlerClassName = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.EXCEPTION_HANDLER_CLASS, m, session);
if(exceptionHandlerClassName!=null){
Class exceptionHandlerClass = findClassForProperty(exceptionHandlerClassName,PersistenceUnitProperties.EXCEPTION_HANDLER_CLASS, loader);
try {
ExceptionHandler exceptionHandler = (ExceptionHandler)buildObjectForClass(exceptionHandlerClass, ExceptionHandler.class);
if (exceptionHandler!=null){
session.setExceptionHandler(exceptionHandler);
} else {
session.handleException(ValidationException.invalidExceptionHandlerClass(exceptionHandlerClassName));
}
} catch (IllegalAccessException e) {
session.handleException(ValidationException.cannotInstantiateExceptionHandlerClass(exceptionHandlerClassName,e));
} catch (PrivilegedActionException e) {
session.handleException(ValidationException.cannotInstantiateExceptionHandlerClass(exceptionHandlerClassName,e));
} catch (InstantiationException e) {
session.handleException(ValidationException.cannotInstantiateExceptionHandlerClass(exceptionHandlerClassName,e));
}
}
}
/**
* Update batch writing setting.
* The method needs to be called in deploy stage.
*/
protected void updateBatchWritingSetting(Map persistenceProperties, ClassLoader loader) {
String batchWritingSettingString = PropertiesHandler.getPropertyValueLogDebug(PersistenceUnitProperties.BATCH_WRITING, persistenceProperties, this.session);
if (batchWritingSettingString != null) {
this.session.getPlatform().setUsesBatchWriting(batchWritingSettingString != BatchWriting.None);
if (batchWritingSettingString == BatchWriting.JDBC) {
this.session.getPlatform().setUsesJDBCBatchWriting(true);
this.session.getPlatform().setUsesNativeBatchWriting(false);
} else if (batchWritingSettingString == BatchWriting.Buffered) {
this.session.getPlatform().setUsesJDBCBatchWriting(false);
this.session.getPlatform().setUsesNativeBatchWriting(false);
} else if (batchWritingSettingString == BatchWriting.OracleJDBC) {
this.session.getPlatform().setUsesNativeBatchWriting(true);
this.session.getPlatform().setUsesJDBCBatchWriting(true);
} else if (batchWritingSettingString == BatchWriting.None) {
// Nothing required.
} else {
if (batchWritingSettingString.equalsIgnoreCase("ExaLogic")) {
batchWritingSettingString = "oracle.toplink.exalogic.batch.DynamicParameterizedBatchWritingMechanism";
}
Class cls = findClassForProperty(batchWritingSettingString, PersistenceUnitProperties.BATCH_WRITING, loader);
BatchWritingMechanism mechanism = null;
try {
Constructor constructor = cls.getConstructor();
mechanism = (BatchWritingMechanism)constructor.newInstance();
} catch (Exception exception) {
if (batchWritingSettingString.indexOf('.') == -1) {
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("ejb30-illegal-property-value", new Object[]{PersistenceUnitProperties.BATCH_WRITING, batchWritingSettingString}));
} else {
throw EntityManagerSetupException.failedToInstantiateProperty(batchWritingSettingString, PersistenceUnitProperties.BATCH_WRITING, exception);
}
}
this.session.getPlatform().setBatchWritingMechanism(mechanism);
}
}
// Set batch size.
String sizeString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.BATCH_WRITING_SIZE, persistenceProperties, this.session);
if (sizeString != null) {
try {
this.session.getPlatform().setMaxBatchWritingSize(Integer.parseInt(sizeString));
} catch (NumberFormatException invalid) {
session.handleException(ValidationException.invalidValueForProperty(sizeString, PersistenceUnitProperties.BATCH_WRITING_SIZE, invalid));
}
}
}
/**
* Load the Metadata Repository for Extensibility
*/
protected void updateMetadataRepository(Map m, ClassLoader loader){
Object metadataSource = EntityManagerFactoryProvider.getConfigPropertyLogDebug(PersistenceUnitProperties.METADATA_SOURCE, m, session);
if (metadataSource != null && metadataSource instanceof MetadataSource){
processor.setMetadataSource((MetadataSource)metadataSource);
} else {
if (metadataSource!=null) {
String repository = (String)metadataSource;
if (repository.equalsIgnoreCase("XML")) {
processor.setMetadataSource(new XMLMetadataSource());
} else {
Class transportClass = findClassForProperty(repository, PersistenceUnitProperties.METADATA_SOURCE, loader);
try {
processor.setMetadataSource((MetadataSource)transportClass.getConstructor().newInstance());
} catch (Exception invalid) {
session.handleException(EntityManagerSetupException.failedToInstantiateProperty(repository, PersistenceUnitProperties.METADATA_SOURCE,invalid));
}
}
}
}
}
/**
* Check for a tuning property and run the tuner preDeploy.
*/
protected void updateTunerPreDeploy(Map m, ClassLoader loader) {
String tuning = (String)EntityManagerFactoryProvider.getConfigPropertyLogDebug(PersistenceUnitProperties.TUNING, m, this.session);
if (tuning != null) {
SessionTuner tuner = null;
if (tuning.equalsIgnoreCase("Safe")) {
tuner = new SafeModeTuner();
} else if (tuning.equalsIgnoreCase("Standard")) {
tuner = new StandardTuner();
} else {
if (tuning.equalsIgnoreCase("ExaLogic")) {
tuning = "oracle.toplink.exalogic.tuning.ExaLogicTuner";
}
Class tunerClass = findClassForProperty(tuning, PersistenceUnitProperties.TUNING, loader);
try {
tuner = (SessionTuner)tunerClass.getConstructor().newInstance();
} catch (Exception invalid) {
this.session.handleException(EntityManagerSetupException.failedToInstantiateProperty(tuning, PersistenceUnitProperties.TUNING, invalid));
}
}
getDatabaseSession().setTuner(tuner);
if (tuner != null) {
tuner.tunePreDeploy(m);
}
}
}
/**
* Check for a tuning property and run the tuner deploy.
*/
protected void updateTunerDeploy(Map m, ClassLoader loader) {
if (getDatabaseSession().getTuner() != null) {
getDatabaseSession().getTuner().tuneDeploy(getDatabaseSession());
}
}
/**
* Check for a tuning property and run the tuner deploy.
*/
protected void updateTunerPostDeploy(Map m, ClassLoader loader) {
if (getDatabaseSession().getTuner() != null) {
getDatabaseSession().getTuner().tunePostDeploy(getDatabaseSession());
}
}
/**
* Allow the deployment metadata to be freed post-deploy to conserve memory.
*/
protected void updateFreeMemory(Map m) {
String freeMemory = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.FREE_METADATA, m, session);
if (freeMemory != null) {
if (freeMemory.equalsIgnoreCase("true")) {
XMLEntityMappingsReader.clear();
} else if (freeMemory.equalsIgnoreCase("false")) {
// default.
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(freeMemory, PersistenceUnitProperties.FREE_METADATA));
}
}
}
/**
* Enable or disable the capability of Native SQL function.
* The method needs to be called in deploy stage.
*/
protected void updateNativeSQLSetting(Map m){
//Set Native SQL flag if it was specified.
String nativeSQLString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.NATIVE_SQL, m, session);
if(nativeSQLString!=null){
if(nativeSQLString.equalsIgnoreCase("true") ){
session.getProject().getLogin().useNativeSQL();
}else if (nativeSQLString.equalsIgnoreCase("false")){
session.getProject().getLogin().dontUseNativeSQL();
}else{
session.handleException(ValidationException.invalidBooleanValueForSettingNativeSQL(nativeSQLString));
}
}
}
/**
* Configure sequencing settings.
*/
protected void updateSequencing(Map m){
String useTable = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.SEQUENCING_SEQUENCE_DEFAULT, m, session);
if (useTable != null) {
if (useTable.equalsIgnoreCase("true")) {
this.session.getPlatform().setDefaultNativeSequenceToTable(true);
} else if (useTable.equalsIgnoreCase("false")) {
this.session.getPlatform().setDefaultNativeSequenceToTable(false);
} else {
this.session.handleException(ValidationException.invalidBooleanValueForProperty(useTable, PersistenceUnitProperties.SEQUENCING_SEQUENCE_DEFAULT));
}
}
}
protected void updateSequencingStart(Map m) {
String local = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.SEQUENCING_START_AT_NEXTVAL, m, session);
try {
if (local != null) {
this.session.getPlatform().setDefaultSeqenceAtNextValue(Boolean.parseBoolean(local));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(local, PersistenceUnitProperties.USE_LOCAL_TIMESTAMP, exception));
}
}
/**
* Load the projectCacheAccessor for JPA project caching
*/
protected void updateProjectCache(Map m, ClassLoader loader){
Object accessor = EntityManagerFactoryProvider.getConfigPropertyLogDebug(PersistenceUnitProperties.PROJECT_CACHE, m, session);
if (accessor != null ) {
if (accessor instanceof ProjectCache) {
projectCacheAccessor = (ProjectCache)accessor;
} else {
String accessorType = (String)accessor;
if (accessorType.equalsIgnoreCase("java-serialization")) {
projectCacheAccessor = new FileBasedProjectCache();
} else {
Class transportClass = findClassForProperty(accessorType, PersistenceUnitProperties.PROJECT_CACHE, loader);
try {
projectCacheAccessor = (ProjectCache)transportClass.getConstructor().newInstance();
} catch (Exception invalid) {
session.handleException(EntityManagerSetupException.failedToInstantiateProperty(accessorType, PersistenceUnitProperties.METADATA_SOURCE,invalid));
}
}
}
}
}
/**
* Enable or disable the capability of Native SQL function.
* The method needs to be called in deploy stage.
*/
protected void updateJPQLParser(Map m) {
// Set JPQL parser if it was specified.
String parser = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JPQL_PARSER, m, this.session);
if (parser != null) {
if (parser.equalsIgnoreCase(ParserType.Hermes)) {
parser = "org.eclipse.persistence.internal.jpa.jpql.HermesParser";
} else if (parser.equalsIgnoreCase(ParserType.ANTLR)) {
parser = "org.eclipse.persistence.queries.ANTLRQueryBuilder";
}
this.session.setProperty(PersistenceUnitProperties.JPQL_PARSER, parser);
}
// Set JPQL parser validation mode if it was specified.
String validation = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JPQL_VALIDATION, m, this.session);
if (validation != null) {
this.session.setProperty(PersistenceUnitProperties.JPQL_VALIDATION, validation);
}
}
/**
* Enable or disable the capability of Native SQL function.
* The method needs to be called in deploy stage.
*/
protected void updateAllowNativeSQLQueriesSetting(Map m){
// Set allow native SQL queries flag if it was specified.
String allowNativeSQLQueriesString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.ALLOW_NATIVE_SQL_QUERIES, m, session);
if (allowNativeSQLQueriesString != null) {
if (allowNativeSQLQueriesString.equalsIgnoreCase("true")) {
session.getProject().setAllowNativeSQLQueries(true);
} else if (allowNativeSQLQueriesString.equalsIgnoreCase("false")) {
session.getProject().setAllowNativeSQLQueries(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForSettingAllowNativeSQLQueries(allowNativeSQLQueriesString));
}
}
}
/**
* Enable or disable SQL casting.
*/
protected void updateSQLCastSetting(Map m) {
//Set Native SQL flag if it was specified.
String sqlCastString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.SQL_CAST, m, session);
if (sqlCastString != null) {
if (sqlCastString.equalsIgnoreCase("true")) {
session.getProject().getLogin().getPlatform().setIsCastRequired(true);
} else if (sqlCastString.equalsIgnoreCase("false")) {
session.getProject().getLogin().getPlatform().setIsCastRequired(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(sqlCastString, PersistenceUnitProperties.SQL_CAST));
}
}
}
/**
* Enable or disable forcing field names to uppercase.
* The method needs to be called in deploy stage.
*/
protected void updateUppercaseSetting(Map m){
//Set Native SQL flag if it was specified.
String uppercaseString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.NATIVE_QUERY_UPPERCASE_COLUMNS, m, session);
if (uppercaseString != null) {
if (uppercaseString.equalsIgnoreCase("true") ){
this.session.getProject().getLogin().setShouldForceFieldNamesToUpperCase(true);
} else if (uppercaseString.equalsIgnoreCase("false")) {
this.session.getProject().getLogin().setShouldForceFieldNamesToUpperCase(false);
} else {
this.session.handleException(ValidationException.invalidBooleanValueForProperty(uppercaseString, PersistenceUnitProperties.NATIVE_QUERY_UPPERCASE_COLUMNS));
}
}
}
/**
/**
* Enable or disable forcing field names to be case insensitive. Implementation of case insensitive column handling relies on setting
* both sides to uppercase (the column names from annotations/xml as well as what is returned from the JDBC/statement)
* The method needs to be called in deploy stage.
*/
public static void updateCaseSensitivitySettings(Map m, MetadataProject project, AbstractSession session){
//Set Native SQL flag if it was specified.
String insensitiveString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.UPPERCASE_COLUMN_NAMES, m, session);
if (insensitiveString == null || insensitiveString.equalsIgnoreCase("true")) {
// Set or default to case in-sensitive.
project.setShouldForceFieldNamesToUpperCase(true);
session.getProject().getLogin().setShouldForceFieldNamesToUpperCase(true);
} else if (insensitiveString.equalsIgnoreCase("false")) {
project.setShouldForceFieldNamesToUpperCase(false);
session.getProject().getLogin().setShouldForceFieldNamesToUpperCase(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(insensitiveString, PersistenceUnitProperties.UPPERCASE_COLUMN_NAMES));
}
}
/**
* Update the default pessimistic lock timeout value.
* @param persistenceProperties the properties map
*/
protected void updatePessimisticLockTimeout(Map persistenceProperties) {
String pessimisticLockTimeout = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.PESSIMISTIC_LOCK_TIMEOUT, persistenceProperties, session);
if (pessimisticLockTimeout != null) {
try {
session.setPessimisticLockTimeoutDefault(Integer.parseInt(pessimisticLockTimeout));
} catch (NumberFormatException invalid) {
session.handleException(ValidationException.invalidValueForProperty(pessimisticLockTimeout, PersistenceUnitProperties.PESSIMISTIC_LOCK_TIMEOUT, invalid));
}
}
}
/**
* Update the default pessimistic lock timeout unit value.
* @param persistenceProperties the properties map
*/
protected void updatePessimisticLockTimeoutUnit(Map persistenceProperties) {
String pessimisticLockTimeoutUnit = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.PESSIMISTIC_LOCK_TIMEOUT_UNIT, persistenceProperties, session);
if (pessimisticLockTimeoutUnit != null) {
try {
TimeUnit unit = TimeUnit.valueOf(pessimisticLockTimeoutUnit);
session.setPessimisticLockTimeoutUnitDefault(unit);
} catch (NumberFormatException invalid) {
session.handleException(ValidationException.invalidValueForProperty(pessimisticLockTimeoutUnit, PersistenceUnitProperties.PESSIMISTIC_LOCK_TIMEOUT_UNIT, invalid));
}
}
}
/**
* Enable or disable statements cached, update statements cache size.
* The method needs to be called in deploy stage.
*/
protected void updateCacheStatementSettings(Map m){
// Cache statements if flag was specified.
String statmentsNeedBeCached = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CACHE_STATEMENTS, m, session);
if (statmentsNeedBeCached!=null) {
if (statmentsNeedBeCached.equalsIgnoreCase("true")) {
if (session.isServerSession() && ((ServerSession)session).getConnectionPools().isEmpty()){
session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "persistence_unit_ignores_statments_cache_setting", new Object[]{null});
} else {
session.getProject().getLogin().setShouldCacheAllStatements(true);
}
} else if (statmentsNeedBeCached.equalsIgnoreCase("false")) {
session.getProject().getLogin().setShouldCacheAllStatements(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForEnableStatmentsCached(statmentsNeedBeCached));
}
}
// Set statement cache size if specified.
String cacheStatementsSize = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CACHE_STATEMENTS_SIZE, m, session);
if (cacheStatementsSize!=null) {
try {
session.getProject().getLogin().setStatementCacheSize(Integer.parseInt(cacheStatementsSize));
} catch (NumberFormatException e) {
session.handleException(ValidationException.invalidCacheStatementsSize(cacheStatementsSize,e.getMessage()));
}
}
}
/**
* Enable or disable default allowing 0 as an id.
*/
@SuppressWarnings("deprecation")
protected void updateAllowZeroIdSetting(Map m) {
String allowZero = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.ALLOW_ZERO_ID, m, this.session);
if (allowZero != null) {
if (allowZero.equalsIgnoreCase("true")) {
Helper.isZeroValidPrimaryKey = true;
} else if (allowZero.equalsIgnoreCase("false")) {
Helper.isZeroValidPrimaryKey = false;
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(allowZero, PersistenceUnitProperties.ALLOW_ZERO_ID));
}
}
}
/**
* Enable or disable default allowing 0 as an id.
*/
protected void updateIdValidation(Map m) {
String idValidationString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.ID_VALIDATION, m, session);
if (idValidationString != null) {
session.getProject().setDefaultIdValidation(IdValidation.valueOf(idValidationString));
}
}
/**
* Sets the SharedCacheMode with values from the jakarta.persistence.sharedCache.mode property. If
* user enters an invalid caching type, valueOf will throw an illegal argument exception, e.g.
* java.lang.IllegalArgumentException: No enum const class
* jakarta.persistence.SharedCacheMode.ALLBOGUS
*/
protected void updateSharedCacheMode(Map m) {
String sharedCacheMode = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.SHARED_CACHE_MODE, m, session);
if (sharedCacheMode != null) {
processor.getProject().setSharedCacheMode(SharedCacheMode.valueOf(sharedCacheMode));
}
}
/**
* sets the TABLE_CREATION_SUFFIX property on the session's project to be applied to all table creation statements (DDL)
*/
protected void updateTableCreationSettings(Map m) {
String tableCreationSuffix = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.TABLE_CREATION_SUFFIX, m, session);
if (tableCreationSuffix != null && tableCreationSuffix.length()>0) {
session.getPlatform().setTableCreationSuffix(tableCreationSuffix);
}
}
/**
* Sets shouldCreateIndicesOnForeignKeys DDL generation option.
*/
protected void updateIndexForeignKeys(Map m) {
String indexForeignKeys = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.DDL_GENERATION_INDEX_FOREIGN_KEYS, m, this.session);
if (indexForeignKeys != null && (indexForeignKeys.length() > 0)) {
if (indexForeignKeys.equalsIgnoreCase("true") ){
this.session.getProject().getLogin().setShouldCreateIndicesOnForeignKeys(true);
} else if (indexForeignKeys.equalsIgnoreCase("false")){
this.session.getProject().getLogin().setShouldCreateIndicesOnForeignKeys(false);
} else {
this.session.handleException(ValidationException.invalidBooleanValueForProperty(indexForeignKeys, PersistenceUnitProperties.DDL_GENERATION_INDEX_FOREIGN_KEYS));
}
}
}
/**
* Enable or disable default temporal mutable setting.
* The method needs to be called in deploy stage.
*/
protected void updateTemporalMutableSetting(Map m) {
// Cache statements if flag was specified.
String temporalMutable = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.TEMPORAL_MUTABLE, m, session);
if (temporalMutable != null) {
if (temporalMutable.equalsIgnoreCase("true")) {
session.getProject().setDefaultTemporalMutable(true);
} else if (temporalMutable.equalsIgnoreCase("false")) {
session.getProject().setDefaultTemporalMutable(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(temporalMutable, PersistenceUnitProperties.TEMPORAL_MUTABLE));
}
}
}
/**
* Copy named queries defined in EclipseLink descriptor into the session if it was indicated to do so.
*/
protected void setDescriptorNamedQueries(Map m) {
// Copy named queries to session if the flag has been specified.
String addNamedQueriesString = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.INCLUDE_DESCRIPTOR_QUERIES, m, session);
if (addNamedQueriesString!=null) {
if (addNamedQueriesString.equalsIgnoreCase("true")) {
session.copyDescriptorNamedQueries(false);
} else {
if (!addNamedQueriesString.equalsIgnoreCase("false")) {
session.handleException(ValidationException.invalidBooleanValueForAddingNamedQueries(addNamedQueriesString));
}
}
}
}
private void updateQueryTimeout(Map persistenceProperties) {
String timeout = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.QUERY_TIMEOUT, persistenceProperties, session);
try {
if (timeout != null) {
session.setQueryTimeoutDefault(Integer.parseInt(timeout));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(timeout, PersistenceUnitProperties.QUERY_TIMEOUT, exception));
}
}
//Bug #456067: Added persistence unit support for timeout units
private void updateQueryTimeoutUnit(Map persistenceProperties) {
String timeoutUnit = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, persistenceProperties, session);
try {
if (timeoutUnit != null) {
TimeUnit unit = TimeUnit.valueOf(timeoutUnit);
session.setQueryTimeoutUnitDefault(unit);
}
} catch (IllegalArgumentException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(timeoutUnit, PersistenceUnitProperties.QUERY_TIMEOUT_UNIT, exception));
}
}
private void updateLockingTimestampDefault(Map persistenceProperties) {
String local = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.USE_LOCAL_TIMESTAMP, persistenceProperties, session);
try {
if (local != null) {
for (ClassDescriptor descriptor: session.getProject().getDescriptors().values()) {
OptimisticLockingPolicy policy = descriptor.getOptimisticLockingPolicy();
if (policy instanceof TimestampLockingPolicy) {
((TimestampLockingPolicy)policy).setUsesServerTime(!Boolean.parseBoolean(local));
}
}
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(local, PersistenceUnitProperties.USE_LOCAL_TIMESTAMP, exception));
}
}
//Bug #333100: Added support for turning off SQL deferral default behavior
private void updateSQLCallDeferralDefault(Map persistenceProperties) {
String defer = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.SQL_CALL_DEFERRAL, persistenceProperties, this.session);
if (defer != null) {
if (defer.equalsIgnoreCase("true")) {
this.session.getProject().setAllowSQLDeferral(true);
} else if (defer.equalsIgnoreCase("false")) {
this.session.getProject().setAllowSQLDeferral(false);
} else {
this.session.handleException(ValidationException.invalidBooleanValueForProperty(defer, PersistenceUnitProperties.SQL_CALL_DEFERRAL));
}
}
}
private void updateNamingIntoIndexed(Map persistenceProperties) {
String namingIntoIndexed = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.NAMING_INTO_INDEXED, persistenceProperties, this.session);
if (namingIntoIndexed != null) {
if (namingIntoIndexed.equalsIgnoreCase("true")) {
this.session.getProject().setNamingIntoIndexed(true);
} else if (namingIntoIndexed.equalsIgnoreCase("false")) {
this.session.getProject().setNamingIntoIndexed(false);
} else {
this.session.handleException(ValidationException.invalidBooleanValueForProperty(namingIntoIndexed, PersistenceUnitProperties.NAMING_INTO_INDEXED));
}
}
}
private void updateConcurrencyManagerWaitTime(Map persistenceProperties) {
String acquireWaitTime = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_ACQUIRE_WAIT_TIME, persistenceProperties, session);
try {
if (acquireWaitTime != null) {
ConcurrencyUtil.SINGLETON.setAcquireWaitTime(Long.parseLong(acquireWaitTime));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(acquireWaitTime, PersistenceUnitProperties.CONCURRENCY_MANAGER_ACQUIRE_WAIT_TIME, exception));
}
}
private void updateConcurrencyManagerBuildObjectCompleteWaitTime(Map persistenceProperties) {
String buildObjectCompleteWaitTime = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_BUILD_OBJECT_COMPLETE_WAIT_TIME, persistenceProperties, session);
try {
if (buildObjectCompleteWaitTime != null) {
ConcurrencyUtil.SINGLETON.setBuildObjectCompleteWaitTime(Long.parseLong(buildObjectCompleteWaitTime));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(buildObjectCompleteWaitTime, PersistenceUnitProperties.CONCURRENCY_MANAGER_BUILD_OBJECT_COMPLETE_WAIT_TIME, exception));
}
}
private void updateConcurrencyManagerMaxAllowedSleepTime(Map persistenceProperties) {
String maxAllowedSleepTime = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_MAX_SLEEP_TIME, persistenceProperties, session);
try {
if (maxAllowedSleepTime != null) {
ConcurrencyUtil.SINGLETON.setMaxAllowedSleepTime(Long.parseLong(maxAllowedSleepTime));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(maxAllowedSleepTime, PersistenceUnitProperties.CONCURRENCY_MANAGER_MAX_SLEEP_TIME, exception));
}
}
private void updateConcurrencyManagerMaxAllowedFrequencyToProduceTinyDumpLogMessage(Map persistenceProperties) {
String maxAllowedSleepTime = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_TINY_MESSAGE, persistenceProperties, session);
try {
if (maxAllowedSleepTime != null) {
ConcurrencyUtil.SINGLETON.setMaxAllowedFrequencyToProduceTinyDumpLogMessage(Long.parseLong(maxAllowedSleepTime));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(maxAllowedSleepTime, PersistenceUnitProperties.CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_TINY_MESSAGE, exception));
}
}
private void updateConcurrencyManagerMaxAllowedFrequencyToProduceMassiveDumpLogMessage(Map persistenceProperties) {
String maxAllowedSleepTime = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_MASSIVE_MESSAGE, persistenceProperties, session);
try {
if (maxAllowedSleepTime != null) {
ConcurrencyUtil.SINGLETON.setMaxAllowedFrequencyToProduceMassiveDumpLogMessage(Long.parseLong(maxAllowedSleepTime));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(maxAllowedSleepTime, PersistenceUnitProperties.CONCURRENCY_MANAGER_MAX_FREQUENCY_DUMP_MASSIVE_MESSAGE, exception));
}
}
private void updateConcurrencyManagerAllowInterruptedExceptionFired(Map persistenceProperties) {
String allowInterruptedExceptionFired = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_ALLOW_INTERRUPTED_EXCEPTION, persistenceProperties, session);
try {
if (allowInterruptedExceptionFired != null) {
ConcurrencyUtil.SINGLETON.setAllowInterruptedExceptionFired(Boolean.parseBoolean(allowInterruptedExceptionFired));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(allowInterruptedExceptionFired, PersistenceUnitProperties.CONCURRENCY_MANAGER_ALLOW_INTERRUPTED_EXCEPTION, exception));
}
}
private void updateConcurrencyManagerAllowConcurrencyExceptionToBeFiredUp(Map persistenceProperties) {
String allowConcurrencyExceptionToBeFiredUp = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_ALLOW_CONCURRENCY_EXCEPTION, persistenceProperties, session);
try {
if (allowConcurrencyExceptionToBeFiredUp != null) {
ConcurrencyUtil.SINGLETON.setAllowConcurrencyExceptionToBeFiredUp(Boolean.parseBoolean(allowConcurrencyExceptionToBeFiredUp));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(allowConcurrencyExceptionToBeFiredUp, PersistenceUnitProperties.CONCURRENCY_MANAGER_ALLOW_CONCURRENCY_EXCEPTION, exception));
}
}
private void updateConcurrencyManagerAllowTakingStackTraceDuringReadLockAcquisition(Map persistenceProperties) {
String allowTakingStackTraceDuringReadLockAcquisition = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK, persistenceProperties, session);
try {
if (allowTakingStackTraceDuringReadLockAcquisition != null) {
ConcurrencyUtil.SINGLETON.setAllowTakingStackTraceDuringReadLockAcquisition(Boolean.parseBoolean(allowTakingStackTraceDuringReadLockAcquisition));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(allowTakingStackTraceDuringReadLockAcquisition, PersistenceUnitProperties.CONCURRENCY_MANAGER_ALLOW_STACK_TRACE_READ_LOCK, exception));
}
}
private void updateConcurrencyManagerUseObjectBuildingSemaphore(Map persistenceProperties) {
String useObjectBuildingSemaphore = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING, persistenceProperties, session);
try {
if (useObjectBuildingSemaphore != null) {
ConcurrencyUtil.SINGLETON.setUseSemaphoreInObjectBuilder(Boolean.parseBoolean(useObjectBuildingSemaphore));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(useObjectBuildingSemaphore, PersistenceUnitProperties.CONCURRENCY_MANAGER_USE_SEMAPHORE_TO_SLOW_DOWN_OBJECT_BUILDING, exception));
}
}
private void updateConcurrencyManagerUseWriteLockManagerSemaphore(Map persistenceProperties) {
String useWriteLockManagerSemaphore = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_USE_SEMAPHORE_TO_SLOW_DOWN_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS, persistenceProperties, session);
try {
if (useWriteLockManagerSemaphore != null) {
ConcurrencyUtil.SINGLETON.setUseSemaphoreToLimitConcurrencyOnWriteLockManagerAcquireRequiredLocks(Boolean.parseBoolean(useWriteLockManagerSemaphore));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(useWriteLockManagerSemaphore, PersistenceUnitProperties.CONCURRENCY_MANAGER_USE_SEMAPHORE_TO_SLOW_DOWN_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS, exception));
}
}
private void updateConcurrencyManagerNoOfThreadsAllowedToObjectBuildInParallel(Map persistenceProperties) {
String noOfThreadsAllowedToObjectBuildInParallel = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_OBJECT_BUILDING_NO_THREADS, persistenceProperties, session);
try {
if (noOfThreadsAllowedToObjectBuildInParallel != null) {
ConcurrencyUtil.SINGLETON.setNoOfThreadsAllowedToObjectBuildInParallel(Integer.parseInt(noOfThreadsAllowedToObjectBuildInParallel));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(noOfThreadsAllowedToObjectBuildInParallel, PersistenceUnitProperties.CONCURRENCY_MANAGER_OBJECT_BUILDING_NO_THREADS, exception));
}
}
private void updateConcurrencyManagerNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel(Map persistenceProperties) {
String noOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_MANAGER_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS_NO_THREADS, persistenceProperties, session);
try {
if (noOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel != null) {
ConcurrencyUtil.SINGLETON.setNoOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel(Integer.parseInt(noOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(noOfThreadsAllowedToDoWriteLockManagerAcquireRequiredLocksInParallel, PersistenceUnitProperties.CONCURRENCY_MANAGER_WRITE_LOCK_MANAGER_ACQUIRE_REQUIRED_LOCKS_NO_THREADS, exception));
}
}
private void updateConcurrencySemaphoreMaxTimePermit(Map persistenceProperties) {
String concurrencySemaphoreMaxTimePermit = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_SEMAPHORE_MAX_TIME_PERMIT, persistenceProperties, session);
try {
if (concurrencySemaphoreMaxTimePermit != null) {
ConcurrencyUtil.SINGLETON.setConcurrencySemaphoreMaxTimePermit(Long.parseLong(concurrencySemaphoreMaxTimePermit));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(concurrencySemaphoreMaxTimePermit, PersistenceUnitProperties.CONCURRENCY_SEMAPHORE_MAX_TIME_PERMIT, exception));
}
}
private void updateConcurrencySemaphoreLogTimeout(Map persistenceProperties) {
String concurrencySemaphoreLogTimeout = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CONCURRENCY_SEMAPHORE_LOG_TIMEOUT, persistenceProperties, session);
try {
if (concurrencySemaphoreLogTimeout != null) {
ConcurrencyUtil.SINGLETON.setConcurrencySemaphoreLogTimeout(Long.parseLong(concurrencySemaphoreLogTimeout));
}
} catch (NumberFormatException exception) {
this.session.handleException(ValidationException.invalidValueForProperty(concurrencySemaphoreLogTimeout, PersistenceUnitProperties.CONCURRENCY_SEMAPHORE_LOG_TIMEOUT, exception));
}
}
/**
* Enable or disable extended logging of JPA L2 cache usage.
* The method needs to be called in deploy stage.
*/
protected void updateAllowExtendedCacheLogging(Map m){
String allowExtendedCacheLogging = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CACHE_EXTENDED_LOGGING, m, session);
if (allowExtendedCacheLogging != null) {
if (allowExtendedCacheLogging.equalsIgnoreCase("true")) {
session.getProject().setAllowExtendedCacheLogging(true);
} else if (allowExtendedCacheLogging.equalsIgnoreCase("false")) {
session.getProject().setAllowExtendedCacheLogging(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(allowExtendedCacheLogging, PersistenceUnitProperties.CACHE_EXTENDED_LOGGING));
}
}
}
/**
* Enable or disable extended thread logging.
* The method needs to be called in deploy stage.
*/
protected void updateAllowExtendedThreadLogging(Map m){
String allowExtendedThreadLogging = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.THREAD_EXTENDED_LOGGING, m, session);
if (allowExtendedThreadLogging != null) {
if (allowExtendedThreadLogging.equalsIgnoreCase("true")) {
session.getProject().setAllowExtendedThreadLogging(true);
} else if (allowExtendedThreadLogging.equalsIgnoreCase("false")) {
session.getProject().setAllowExtendedThreadLogging(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(allowExtendedThreadLogging, PersistenceUnitProperties.THREAD_EXTENDED_LOGGING));
}
}
}
/**
* Enable or disable thread dump addition to extended thread logging.
* The method needs to be called in deploy stage.
*/
protected void updateAllowExtendedThreadLoggingThreadDump(Map m){
String allowExtendedThreadLoggingThreadDump = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.THREAD_EXTENDED_LOGGING_THREADDUMP, m, session);
if (allowExtendedThreadLoggingThreadDump != null) {
if (allowExtendedThreadLoggingThreadDump.equalsIgnoreCase("true")) {
session.getProject().setAllowExtendedThreadLoggingThreadDump(true);
} else if (allowExtendedThreadLoggingThreadDump.equalsIgnoreCase("false")) {
session.getProject().setAllowExtendedThreadLoggingThreadDump(false);
} else {
session.handleException(ValidationException.invalidBooleanValueForProperty(allowExtendedThreadLoggingThreadDump, PersistenceUnitProperties.THREAD_EXTENDED_LOGGING_THREADDUMP));
}
}
}
/**
* If Bean Validation is enabled, bootstraps Bean Validation on descriptors.
* @param puProperties merged properties for this persistence unit
*/
private void addBeanValidationListeners(Map puProperties, ClassLoader appClassLoader) {
ValidationMode validationMode = getValidationMode(persistenceUnitInfo, puProperties);
if (validationMode == ValidationMode.AUTO || validationMode == ValidationMode.CALLBACK) {
// BeanValidationInitializationHelper contains static reference to jakarta.validation.* classes. We need to support
// environment where these classes are not available.
// To guard against some vms that eagerly resolve, reflectively load class to prevent any static reference to it
String helperClassName = "org.eclipse.persistence.internal.jpa.deployment.BeanValidationInitializationHelper$BeanValidationInitializationHelperImpl";
Class helperClass;
try {
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
try {
helperClass = AccessController.doPrivileged(
new PrivilegedClassForName(helperClassName, true, appClassLoader));
} catch (Throwable t) {
// Try the ClassLoader that loaded Eclipselink classes
ClassLoader eclipseLinkClassLoader = EntityManagerSetupImpl.class.getClassLoader();
helperClass = AccessController.doPrivileged(new PrivilegedClassForName(helperClassName, true, eclipseLinkClassLoader));
}
} else {
try {
helperClass = PrivilegedAccessHelper.getClassForName(helperClassName, true, appClassLoader);
} catch (Throwable t) {
// Try the ClassLoader that loaded Eclipselink classes
ClassLoader eclipseLinkClassLoader = EntityManagerSetupImpl.class.getClassLoader();
helperClass = PrivilegedAccessHelper.getClassForName(helperClassName, true, eclipseLinkClassLoader);
}
}
BeanValidationInitializationHelper beanValidationInitializationHelper = (BeanValidationInitializationHelper)helperClass.getConstructor().newInstance();
beanValidationInitializationHelper.bootstrapBeanValidation(puProperties, session, appClassLoader);
} catch (Throwable e) { //Catching Throwable to catch any linkage errors on vms that resolve eagerly
if (validationMode == ValidationMode.CALLBACK) {
throw PersistenceUnitLoadingException.exceptionObtainingRequiredBeanValidatorFactory(e);
} // else validationMode == ValidationMode.AUTO. Log a message, Ignore the exception
this.session.log(SessionLog.FINEST, SessionLog.JPA, "validation_factory_not_initialized", new Object[]{ e.getMessage() });
}
}
}
/**
* Validation mode from information in persistence.xml and properties specified at EMF creation
* @param persitenceUnitInfo PersitenceUnitInfo instance for this persistence unit
* @param puProperties merged properties for this persistence unit
* @return validation mode
*/
private static ValidationMode getValidationMode(PersistenceUnitInfo persitenceUnitInfo, Map puProperties) {
//Check if overridden at emf creation
String validationModeAtEMFCreation = (String) puProperties.get(PersistenceUnitProperties.VALIDATION_MODE);
if(validationModeAtEMFCreation != null) {
// User will receive IllegalArgumentException if an invalid mode has been specified
return ValidationMode.valueOf(validationModeAtEMFCreation.toUpperCase(Locale.ROOT));
}
//otherwise:
ValidationMode validationMode = null;
// Initialize with value in persitence.xml
// Using reflection to call getValidationMode to prevent blowing up while we are running in JPA 1.0 environment
// (This would be all JavaEE5 appservers) where PersistenceUnitInfo does not implement method getValidationMode().
try {
Method method = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
method = AccessController.doPrivileged(new PrivilegedGetDeclaredMethod(PersistenceUnitInfo.class, "getValidationMode", null));
validationMode = (ValidationMode) AccessController.doPrivileged(new PrivilegedMethodInvoker(method, persitenceUnitInfo));
} else {
method = PrivilegedAccessHelper.getDeclaredMethod(PersistenceUnitInfo.class, "getValidationMode", null);
validationMode = (ValidationMode) PrivilegedAccessHelper.invokeMethod(method, persitenceUnitInfo, null);
}
} catch (Throwable exception) {
// We are running in JavaEE5 environment. Catch and swallow any exceptions and return null.
}
if(validationMode == null) {
// Default to AUTO as specified in JPA spec.
validationMode = ValidationMode.AUTO;
}
return validationMode;
}
/**
* INTERNAL:
* Return an instance of Metamodel interface for access to the
* metamodel of the persistence unit.
* This method will complete any initialization done in the predeploy phase
* of deployment.
* @return Metamodel instance
* @since Java Persistence 2.0
*/
public Metamodel getMetamodel(ClassLoader classLoader) {
preInitializeMetamodel();
if (!((MetamodelImpl)metaModel).isInitialized()){
((MetamodelImpl)metaModel).initialize(classLoader);
// If the canonical metamodel classes exist, initialize them
initializeCanonicalMetamodel(metaModel);
}
return metaModel;
}
/**
* INTERNAL:
* Initialize the Canonical Metamodel classes generated by EclipseLink
* @since Java Persistence 2.0
*/
protected void initializeCanonicalMetamodel(Metamodel model) {
// 338837: verify that the collection is not empty - this would mean entities did not make it into the search path
if(null == model.getManagedTypes() || model.getManagedTypes().isEmpty()) {
getSession().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_type_collection_empty");
}
for (ManagedType manType : model.getManagedTypes()) {
boolean classInitialized = false;
String className = MetadataHelper.getQualifiedCanonicalName(manType.getJavaType().getName(), getSession());
try {
Class clazz = (Class)this.getSession().getDatasourcePlatform().convertObject(className, ClassConstants.CLASS);
classInitialized=true;
this.getSession().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_canonical_model_class_found", className);
String fieldName = "";
for(Object attribute : manType.getDeclaredAttributes()) {
try {
fieldName = ((Attribute)attribute).getName();
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
AccessController.doPrivileged(new PrivilegedGetDeclaredField(clazz, fieldName, false)).set(clazz, attribute);
} else {
PrivilegedAccessHelper.getDeclaredField(clazz, fieldName, false).set(clazz, attribute);
}
} catch (NoSuchFieldException nsfe) {
// Ignore fields missing in canonical model (dclarke bug 346106)
} catch (Exception e) {
ValidationException v = ValidationException.invalidFieldForClass(fieldName, clazz);
v.setInternalException(e);
throw v;
}
}
} catch (ConversionException exception){
}
if (!classInitialized) {
getSession().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_canonical_model_class_not_found", className);
}
}
}
/**
* INTERNAL:
* Convenience function to allow us to reset the Metamodel
* in the possible case that we want to regenerate it.
* This function is outside of the JPA 2.0 specification.
* @param aMetamodel
* @since Java Persistence 2.0
*/
public void setMetamodel(Metamodel aMetamodel) {
this.metaModel = aMetamodel;
}
public boolean mustBeCompositeMember() {
return mustBeCompositeMember(this.persistenceUnitInfo);
}
public boolean isCompositeMember() {
return this.compositeEmSetupImpl != null;
}
public boolean isComposite() {
return this.compositeMemberEmSetupImpls != null;
}
public static boolean mustBeCompositeMember(PersistenceUnitInfo puInfo) {
String mustBeCompositeMemberStr = PropertiesHandler.getPropertyValue(PersistenceUnitProperties.COMPOSITE_UNIT_MEMBER, puInfo.getProperties(), false);
if(mustBeCompositeMemberStr != null) {
return mustBeCompositeMemberStr.equals("true");
} else {
return false;
}
}
public static boolean isComposite(PersistenceUnitInfo puInfo) {
String isCompositeString = PropertiesHandler.getPropertyValue(PersistenceUnitProperties.COMPOSITE_UNIT, puInfo.getProperties(), false);
if(isCompositeString != null) {
return isCompositeString.equals("true");
} else {
return false;
}
}
public void setCompositeEmSetupImpl(EntityManagerSetupImpl compositeEmSetupImpl) {
this.compositeEmSetupImpl = compositeEmSetupImpl;
}
public EntityManagerSetupImpl getCompositeEmSetupImpl() {
return this.compositeEmSetupImpl;
}
// predeploy method will be used for static weaving
public void setStaticWeaveInfo(StaticWeaveInfo staticWeaveInfo) {
this.staticWeaveInfo = staticWeaveInfo;
}
protected void predeployCompositeMembers(Map predeployProperties, ClassLoader tempClassLoader) {
// get all puInfos found in jar-files specified in composite's persistence.xml
// all these puInfos are not composite because composites are recursively "taken apart", too.
Set compositeMemberPuInfos = getCompositeMemberPuInfoSet(persistenceUnitInfo, predeployProperties);
// makes sure each member has a non-null property, overrides where required properties with composite's predeploy properties.
updateCompositeMembersProperties(compositeMemberPuInfos, predeployProperties);
// Don't log these properties - may contain passwords. The properties will be logged by contained persistence units.
Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, predeployProperties);
this.compositeMemberEmSetupImpls = new HashSet(compositeMemberPuInfos.size());
this.processor = new MetadataProcessor();
if (enableWeaving) {
this.weaver = new PersistenceWeaver(new HashMap());
}
// create containedEmSetupImpls and predeploy them for the first time.
// predeploy divided in three stages (modes):
// all composite members should complete a stage before any of them can move to the next one.
for (SEPersistenceUnitInfo compositeMemberPuInfo : compositeMemberPuInfos) {
// set composite's temporary classloader
compositeMemberPuInfo.setNewTempClassLoader(tempClassLoader);
String containedPuName = compositeMemberPuInfo.getPersistenceUnitName();
EntityManagerSetupImpl containedEmSetupImpl = new EntityManagerSetupImpl(containedPuName, containedPuName);
// set composite
containedEmSetupImpl.setCompositeEmSetupImpl(this);
// non-null only in case predeploy is used for static weaving
containedEmSetupImpl.setStaticWeaveInfo(this.staticWeaveInfo);
// the properties guaranteed to be non-null after updateCompositeMemberProperties call
Map compositeMemberProperties = (Map)compositeMemberMapOfProperties.get(containedPuName);
containedEmSetupImpl.predeploy(compositeMemberPuInfo, compositeMemberProperties);
// reset temporary classloader back to the original
compositeMemberPuInfo.setNewTempClassLoader(compositeMemberPuInfo.getClassLoader());
this.compositeMemberEmSetupImpls.add(containedEmSetupImpl);
}
// after the first loop containedEmSetupImpls are in HalfPredeployed state,
// mode = COMPOSITE_MEMBER_MIDDLE mode
for(EntityManagerSetupImpl containedEmSetupImpl : this.compositeMemberEmSetupImpls) {
// properties not used, puInfo already set
containedEmSetupImpl.predeploy(null, null);
}
// after the second loop containedEmSetupImpls are still in HalfPredeployed state,
// mode = COMPOSITE_MEMBER_FINAL mode
for(EntityManagerSetupImpl containedEmSetupImpl : this.compositeMemberEmSetupImpls) {
// properties not used, puInfo already set
PersistenceWeaver containedWeaver = (PersistenceWeaver)containedEmSetupImpl.predeploy(null, null);
// containedEmSetupImpl is finally in Predeployed state.
// if both composite and composite member weavings enabled copy class details from member's weaver to composite's one.
if(enableWeaving && containedWeaver != null) {
this.weaver.getClassDetailsMap().putAll(containedWeaver.getClassDetailsMap());
}
}
if(enableWeaving && this.weaver.getClassDetailsMap().isEmpty()) {
this.weaver = null;
}
}
protected void deployCompositeMembers(Map deployProperties, ClassLoader realClassLoader) {
// Don't log these properties - may contain passwords. The properties will be logged by contained persistence units.
Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, deployProperties);
for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) {
// the properties guaranteed to be non-null after updateCompositeMemberProperties call
Map compositeMemberProperties = (Map)compositeMemberMapOfProperties.get(compositeMemberEmSetupImpl.getPersistenceUnitInfo().getPersistenceUnitName());
compositeMemberEmSetupImpl.deploy(realClassLoader, compositeMemberProperties);
AbstractSession containedSession = compositeMemberEmSetupImpl.getSession();
((SessionBroker)session).registerSession(containedSession.getName(), containedSession);
}
}
/**
* INTERNAL:
* Cause the first phase of metamodel initialization. This phase involves detecting the classes involved
* and build metamodel instances for them.
*/
public void preInitializeMetamodel(){
// perform lazy initialisation
Metamodel tempMetaModel = null;
if (null == metaModel){
// 338837: verify that the collection is not empty - this would mean entities did not make it into the search path
tempMetaModel = new MetamodelImpl(this);
// set variable after init has executed without exception
metaModel = tempMetaModel;
}
}
/**
* INTERNAL:
* First phase of canonical metamodel initialization. For each class the metamodel is aware of, check
* for a canonical metamodel class and initialize each attribute in it with a proxy that can cause the
* rest of the metamodel population. Attributes are found reflectively rather than through the metamodel
* to avoid having to further initialize the metamodel.
* @param factory
*/
public void preInitializeCanonicalMetamodel(EntityManagerFactoryImpl factory){
// 338837: verify that the collection is not empty - this would mean entities did not make it into the search path
if(null == metaModel.getManagedTypes() || metaModel.getManagedTypes().isEmpty()) {
getSession().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_type_collection_empty");
}
for (ManagedType manType : metaModel.getManagedTypes()) {
boolean classInitialized = false;
String className = MetadataHelper.getQualifiedCanonicalName(((ManagedTypeImpl)manType).getJavaTypeName(), getSession());
try {
Class clazz = (Class)this.getSession().getDatasourcePlatform().convertObject(className, ClassConstants.CLASS);
classInitialized=true;
this.getSession().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_canonical_model_class_found", className);
Field[] fields = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
fields = AccessController.doPrivileged(new PrivilegedGetDeclaredFields(clazz));
} else {
fields = PrivilegedAccessHelper.getDeclaredFields(clazz);
}
for(Field attribute : fields) {
if (Attribute.class.isAssignableFrom(attribute.getType())){
Object assignedAttribute = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){
assignedAttribute = AccessController.doPrivileged(new PrivilegedGetValueFromField(attribute, null));
} else {
assignedAttribute =PrivilegedAccessHelper.getValueFromField(attribute, null);
}
AttributeProxyImpl proxy = null;
if (assignedAttribute == null){
if (SingularAttribute.class.isAssignableFrom(attribute.getType())){
proxy = new SingularAttributeProxyImpl();
} else if (MapAttribute.class.isAssignableFrom(attribute.getType())){
proxy = new MapAttributeProxyImpl();
} else if (SetAttribute.class.isAssignableFrom(attribute.getType())){
proxy = new SetAttributeProxyImpl();
} else if (ListAttribute.class.isAssignableFrom(attribute.getType())){
proxy = new ListAttributeProxyImpl();
} else if (CollectionAttribute.class.isAssignableFrom(attribute.getType())){
proxy = new CollectionAttributeProxyImpl();
}
if (proxy != null){
attribute.setAccessible(true);
attribute.set(null, proxy);
}
} else if (assignedAttribute instanceof AttributeProxyImpl){
proxy = (AttributeProxyImpl)assignedAttribute;
}
if (proxy != null){
proxy.addFactory(factory);
}
}
}
} catch (PrivilegedActionException pae){
getSession().logThrowable(SessionLog.FINEST, SessionLog.METAMODEL, pae);
} catch (IllegalAccessException iae){
getSession().logThrowable(SessionLog.FINEST, SessionLog.METAMODEL, iae);
} catch (ConversionException ce){
}
if (!classInitialized) {
getSession().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_canonical_model_class_not_found", className);
}
}
}
/*
* Overide composite member properties' map with a new one, which
* has (possibly empty but non-null) properties for each composite member,
* for required properties overrides values with those from composite properties.
*/
protected void updateCompositeMembersProperties(Map compositeProperties) {
Set compositePuInfos = new HashSet(compositeMemberEmSetupImpls.size());
for (EntityManagerSetupImpl compositeMemberEmSetupImpl : compositeMemberEmSetupImpls) {
compositePuInfos.add((SEPersistenceUnitInfo)compositeMemberEmSetupImpl.persistenceUnitInfo);
}
updateCompositeMembersProperties(compositePuInfos, compositeProperties);
}
/*
* Overide composite member properties' map with a new one, which
* has (possibly empty but non-null) properties for each composite member,
* for required properties overrides values with those from composite properties.
* Parameter compositePuInfo indicates whether compositeMemberPreoperties should be merged (overriding) with its puInfo properties
* (false for predeploy, true for deploy).
*/
protected void updateCompositeMembersProperties(Set compositePuInfos, Map compositeProperties) {
// Don't log these properties - may contain passwords. The properties will be logged by contained persistence units.
Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, compositeProperties);
Map newCompositeMemberMapOfProperties;
if (compositeMemberMapOfProperties == null) {
newCompositeMemberMapOfProperties = new HashMap(compositePuInfos.size());
} else {
// Don't alter user-supplied properties' map - create a copy instead
newCompositeMemberMapOfProperties = new HashMap(compositeMemberMapOfProperties);
}
for (SEPersistenceUnitInfo compositePuInfo : compositePuInfos) {
String compositeMemberPuName = compositePuInfo.getPersistenceUnitName();
Map compositeMemberProperties = (Map)newCompositeMemberMapOfProperties.get(compositeMemberPuName);
Map newCompositeMemberProperties;
if (compositeMemberProperties == null) {
newCompositeMemberProperties = new HashMap();
} else {
// Don't alter user-supplied properties - create a copy instead
newCompositeMemberProperties = new HashMap(compositeMemberProperties);
}
overrideMemberProperties(newCompositeMemberProperties, compositeProperties);
newCompositeMemberProperties = mergeMaps(newCompositeMemberProperties, compositePuInfo.getProperties());
translateOldProperties(newCompositeMemberProperties, session);
newCompositeMemberMapOfProperties.put(compositeMemberPuName, newCompositeMemberProperties);
}
// set the new COMPOSITE_PROPERTIES into compositeProperties
compositeProperties.put(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, newCompositeMemberMapOfProperties);
}
/*
* For required properties overrides values with those from composite properties.
*/
protected static void overrideMemberProperties(Map memberProperties, Map compositeProperties) {
String transactionTypeProp = (String)compositeProperties.get(PersistenceUnitProperties.TRANSACTION_TYPE);
if (transactionTypeProp != null) {
memberProperties.put(PersistenceUnitProperties.TRANSACTION_TYPE, transactionTypeProp);
} else {
memberProperties.remove(PersistenceUnitProperties.TRANSACTION_TYPE);
}
String serverPlatformProp = (String)compositeProperties.get(PersistenceUnitProperties.TARGET_SERVER);
if (serverPlatformProp != null) {
memberProperties.put(PersistenceUnitProperties.TARGET_SERVER, serverPlatformProp);
} else {
memberProperties.remove(PersistenceUnitProperties.TARGET_SERVER);
}
Boolean isValidationOnly = (Boolean)compositeProperties.get(PersistenceUnitProperties.VALIDATION_ONLY_PROPERTY);
if (isValidationOnly != null) {
memberProperties.put(PersistenceUnitProperties.VALIDATION_ONLY_PROPERTY, isValidationOnly);
} else {
memberProperties.remove(PersistenceUnitProperties.VALIDATION_ONLY_PROPERTY);
}
}
/*
* If a member is composite then add its members instead.
* All members' puNames must be unique.
* Return a Map of composite member SEPersistenceUnitInfo keyed by persistence unit name.
*/
protected static Map getCompositeMemberPuInfoMap(PersistenceUnitInfo puInfo, Map predeployProperties) {
Set memeberPuInfoSet = PersistenceUnitProcessor.getPersistenceUnits(puInfo.getClassLoader(), predeployProperties, puInfo.getJarFileUrls());
HashMap memberPuInfoMap = new HashMap(memeberPuInfoSet.size());
for (SEPersistenceUnitInfo memberPuInfo : memeberPuInfoSet) {
// override transaction type with composite's transaction type
memberPuInfo.setTransactionType(puInfo.getTransactionType());
// override properties that should be overridden by composit's properties
overrideMemberProperties(memberPuInfo.getProperties(), puInfo.getProperties());
if (isComposite(memberPuInfo)) {
Map containedMemberPuInfoMap = getCompositeMemberPuInfoMap(memberPuInfo, memberPuInfo.getProperties());
Iterator> it = containedMemberPuInfoMap.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry = it.next();
String containedMemberPuName = entry.getKey();
SEPersistenceUnitInfo containedMemberPuInfo = entry.getValue();
SEPersistenceUnitInfo anotherMemeberPuInfo = memberPuInfoMap.get(containedMemberPuName);
if (anotherMemeberPuInfo == null) {
memberPuInfoMap.put(containedMemberPuName, containedMemberPuInfo);
} else {
throwPersistenceUnitNameAlreadyInUseException(containedMemberPuName, containedMemberPuInfo, anotherMemeberPuInfo);
}
}
} else {
String memberPuName = memberPuInfo.getPersistenceUnitName();
SEPersistenceUnitInfo anotherMemeberPuInfo = memberPuInfoMap.get(memberPuName);
if (anotherMemeberPuInfo == null) {
memberPuInfoMap.put(memberPuName, memberPuInfo);
} else {
throwPersistenceUnitNameAlreadyInUseException(memberPuName, memberPuInfo, anotherMemeberPuInfo);
}
}
}
return memberPuInfoMap;
}
/*
* If a member is composite then add its members instead.
* All members' puNames must be unique.
* Return a Set of composite member SEPersistenceUnitInfo.
*/
protected static Set getCompositeMemberPuInfoSet(PersistenceUnitInfo puInfo, Map predeployProperties) {
return new HashSet(getCompositeMemberPuInfoMap(puInfo, predeployProperties).values());
}
public static void throwPersistenceUnitNameAlreadyInUseException(String puName, PersistenceUnitInfo newPuInfo, PersistenceUnitInfo exsitingPuInfo) {
String puUrl;
String anotherPuUrl;
try {
puUrl = URLDecoder.decode(newPuInfo.getPersistenceUnitRootUrl().toString(), "UTF8");
anotherPuUrl = URLDecoder.decode(exsitingPuInfo.getPersistenceUnitRootUrl().toString(), "UTF8");
} catch (UnsupportedEncodingException e) {
puUrl = newPuInfo.getPersistenceUnitRootUrl().toString();
anotherPuUrl = exsitingPuInfo.getPersistenceUnitRootUrl().toString();
}
throw PersistenceUnitLoadingException.persistenceUnitNameAlreadyInUse(puName, puUrl, anotherPuUrl);
}
/**
* Create a new version of this EntityManagerSetupImpl and cache it. Prepare "this" EntityManagerSetupImpl
* for garbage collection.
*
* This call will mean any users of this EntityManagerSetupImpl will get the new version the next time
* they look it up (for instance and EntityManager creation time)
* @param properties
* @return
*/
public EntityManagerSetupImpl refreshMetadata(Map properties){
String sessionName = getSessionName();
String uniqueName = getPersistenceUnitUniqueName();
EntityManagerSetupImpl newSetupImpl = new EntityManagerSetupImpl(uniqueName, sessionName);
newSetupImpl.setIsInContainerMode(isInContainerMode);
newSetupImpl.enableWeaving = enableWeaving;
Map refreshProperties = new HashMap();
refreshProperties.putAll(getSession().getProperties());
if (properties != null){
refreshProperties.putAll(properties);
}
newSetupImpl.predeploy(getPersistenceUnitInfo(), refreshProperties);
// newSetupImpl has been already predeployed, predeploy will just increment factoryCount.
if (!isInContainerMode) {
newSetupImpl.predeploy(getPersistenceUnitInfo(), refreshProperties);
}
synchronized (EntityManagerFactoryProvider.emSetupImpls) {
SessionManager.getManager().getSessions().remove(sessionName, getSession());
if (EntityManagerFactoryProvider.emSetupImpls.get(sessionName).equals(this)){
EntityManagerFactoryProvider.emSetupImpls.remove(sessionName);
}
setIsMetadataExpired(true);
//stop this EntityManagerSetupImpl's session from processing refresh commands. The new session should listen instead.
getSession().setRefreshMetadataListener(null);
EntityManagerFactoryProvider.addEntityManagerSetupImpl(sessionName, newSetupImpl);
}
return newSetupImpl;
}
/**
* This method is just a wrapper on refreshMetadata so that core does not need a dependency on JPA
* due to the EntityManagerSetupImpl return value. This method satisfies the MetedataRefreshListener implementation
* and is called by incoming RCM refresh commands
*
* @see refreshMetadata
*/
@Override
public void triggerMetadataRefresh(Map properties){
refreshMetadata(properties);
}
/**
* INTERNAL:
* Generate the DDL per the properties specified.
*/
public void writeDDL(Map props, DatabaseSessionImpl session, ClassLoader classLoader) {
if (this.compositeMemberEmSetupImpls == null) {
// Generate the DDL if we find either EclipseLink or JPA DDL generation properties.
// Note, we do one or the other, that is, we do not mix the properties by default
// but we may use some with both, e.g. APP_LOCATION. EclipseLink properties
// override JPA properties.
if (hasConfigProperty(DDL_GENERATION, props)) {
// We have EclipseLink DDL generation properties.
String ddlGeneration = getConfigPropertyAsString(DDL_GENERATION, props).toLowerCase(Locale.ROOT);
if (! ddlGeneration.equals(NONE)) {
writeDDL(ddlGeneration, props, session, classLoader);
}
} else {
// Look for JPA schema generation properties.
// Schema generation for the database.
if (hasConfigProperty(SCHEMA_GENERATION_DATABASE_ACTION, props)) {
String databaseGenerationAction = getConfigPropertyAsString(SCHEMA_GENERATION_DATABASE_ACTION, props).toLowerCase(Locale.ROOT);
if (! databaseGenerationAction.equals(SCHEMA_GENERATION_NONE_ACTION)) {
if (databaseGenerationAction.equals(SCHEMA_GENERATION_CREATE_ACTION)) {
writeDDL(SCHEMA_GENERATION_CREATE_SOURCE, SCHEMA_GENERATION_CREATE_SCRIPT_SOURCE, TableCreationType.CREATE, props, session, classLoader);
} else if (databaseGenerationAction.equals(PersistenceUnitProperties.CREATE_OR_EXTEND)) {
writeDDL(SCHEMA_GENERATION_CREATE_SOURCE, SCHEMA_GENERATION_CREATE_SCRIPT_SOURCE, TableCreationType.EXTEND, props, session, classLoader);
} else if (databaseGenerationAction.equals(SCHEMA_GENERATION_DROP_ACTION)) {
writeDDL(SCHEMA_GENERATION_DROP_SOURCE, SCHEMA_GENERATION_DROP_SCRIPT_SOURCE, TableCreationType.DROP, props, session, classLoader);
} else if (databaseGenerationAction.equals(SCHEMA_GENERATION_DROP_AND_CREATE_ACTION)) {
writeDDL(SCHEMA_GENERATION_DROP_SOURCE, SCHEMA_GENERATION_DROP_SCRIPT_SOURCE, TableCreationType.DROP, props, session, classLoader);
writeDDL(SCHEMA_GENERATION_CREATE_SOURCE, SCHEMA_GENERATION_CREATE_SCRIPT_SOURCE, TableCreationType.CREATE, props, session, classLoader);
} else {
String validOptions = SCHEMA_GENERATION_CREATE_ACTION + ", " + SCHEMA_GENERATION_DROP_ACTION + ", " + SCHEMA_GENERATION_DROP_AND_CREATE_ACTION + ", " + PersistenceUnitProperties.CREATE_OR_EXTEND;
session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "ddl_generation_unknown_property_value", new Object[] {SCHEMA_GENERATION_DATABASE_ACTION, databaseGenerationAction, persistenceUnitInfo.getPersistenceUnitName(), validOptions});
}
}
}
// Schema generation for target scripts.
if (hasConfigProperty(SCHEMA_GENERATION_SCRIPTS_ACTION, props)) {
String scriptsGenerationAction = getConfigPropertyAsString(SCHEMA_GENERATION_SCRIPTS_ACTION, props).toLowerCase(Locale.ROOT);
if (! scriptsGenerationAction.equals(SCHEMA_GENERATION_NONE_ACTION)) {
if (scriptsGenerationAction.equals(SCHEMA_GENERATION_CREATE_ACTION)) {
writeMetadataDDLToScript(TableCreationType.CREATE, props, session, classLoader);
} else if (scriptsGenerationAction.equals(PersistenceUnitProperties.CREATE_OR_EXTEND)) {
writeMetadataDDLToScript(TableCreationType.EXTEND, props, session, classLoader);
} else if (scriptsGenerationAction.equals(SCHEMA_GENERATION_DROP_ACTION)) {
writeMetadataDDLToScript(TableCreationType.DROP, props, session, classLoader);
} else if (scriptsGenerationAction.equals(SCHEMA_GENERATION_DROP_AND_CREATE_ACTION)) {
writeMetadataDDLToScript(TableCreationType.DROP_AND_CREATE, props, session, classLoader);
} else {
String validOptions = SCHEMA_GENERATION_CREATE_ACTION + ", " + SCHEMA_GENERATION_DROP_ACTION + ", " + SCHEMA_GENERATION_DROP_AND_CREATE_ACTION;
session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "ddl_generation_unknown_property_value", new Object[] {SCHEMA_GENERATION_SCRIPTS_ACTION, scriptsGenerationAction, persistenceUnitInfo.getPersistenceUnitName(), validOptions});
}
}
}
// Once we've generated any and all DDL, check for load scripts.
writeSourceScriptToDatabase(getConfigProperty(SCHEMA_GENERATION_SQL_LOAD_SCRIPT_SOURCE, props), session, classLoader);
}
} else {
// composite
Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, props);
for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) {
// the properties guaranteed to be non-null after updateCompositeMemberProperties call
Map compositeMemberProperties = (Map)compositeMemberMapOfProperties.get(compositeMemberEmSetupImpl.getPersistenceUnitInfo().getPersistenceUnitName());
compositeMemberEmSetupImpl.writeDDL(compositeMemberProperties, session, classLoader);
}
}
}
/**
* INTERNAL:
* Generate the DDL from the persistence unit metadata. This DDL generation
* utilizes the EclipseLink DDL properties.
*/
protected void writeDDL(String ddlGeneration, Map props, DatabaseSessionImpl session, ClassLoader classLoader) {
// By default the table creation type will be 'none'.
TableCreationType ddlType = TableCreationType.NONE;
if (ddlGeneration.equals(PersistenceUnitProperties.CREATE_ONLY)) {
ddlType = TableCreationType.CREATE;
} else if (ddlGeneration.equals(PersistenceUnitProperties.DROP_ONLY)) {
ddlType = TableCreationType.DROP;
} else if (ddlGeneration.equals(PersistenceUnitProperties.DROP_AND_CREATE)) {
ddlType = TableCreationType.DROP_AND_CREATE;
} else if (ddlGeneration.equals(PersistenceUnitProperties.CREATE_OR_EXTEND)) {
ddlType = TableCreationType.EXTEND;
} else {
// Log a warning if we have an unknown ddl generation.
String validOptions = PersistenceUnitProperties.NONE + ", " +
PersistenceUnitProperties.CREATE_ONLY + ", " +
PersistenceUnitProperties.DROP_ONLY + ", " +
PersistenceUnitProperties.DROP_AND_CREATE + ", " +
PersistenceUnitProperties.CREATE_OR_EXTEND;
session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "ddl_generation_unknown_property_value", new Object[] {PersistenceUnitProperties.DDL_GENERATION, ddlGeneration, persistenceUnitInfo.getPersistenceUnitName(), validOptions});
}
if (ddlType != TableCreationType.NONE) {
String ddlGenerationMode = getConfigPropertyAsString(PersistenceUnitProperties.DDL_GENERATION_MODE, props, PersistenceUnitProperties.DEFAULT_DDL_GENERATION_MODE);
// Optimize for cases where the value is explicitly set to NONE
if (! ddlGenerationMode.equals(NONE)) {
if (isCompositeMember()) {
// debug output added to make it easier to navigate the log because the method is called outside of composite member deploy
session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_begin_call", new Object[]{"generateDDL", persistenceUnitInfo.getPersistenceUnitName(), state});
}
SchemaManager mgr = new SchemaManager(session);
if (ddlGenerationMode.equals(PersistenceUnitProperties.DDL_DATABASE_GENERATION) || ddlGenerationMode.equals(PersistenceUnitProperties.DDL_BOTH_GENERATION)) {
writeDDLToDatabase(mgr, ddlType);
}
if (ddlGenerationMode.equals(PersistenceUnitProperties.DDL_SQL_SCRIPT_GENERATION)|| ddlGenerationMode.equals(PersistenceUnitProperties.DDL_BOTH_GENERATION)) {
String appLocation = getConfigPropertyAsString(PersistenceUnitProperties.APP_LOCATION, props, PersistenceUnitProperties.DEFAULT_APP_LOCATION);
// These could be a string (file name urls) or actual writers.
Object createDDLJdbc = getConfigProperty(PersistenceUnitProperties.CREATE_JDBC_DDL_FILE, props, PersistenceUnitProperties.DEFAULT_CREATE_JDBC_FILE_NAME);
Object dropDDLJdbc = getConfigProperty(PersistenceUnitProperties.DROP_JDBC_DDL_FILE, props, PersistenceUnitProperties.DEFAULT_DROP_JDBC_FILE_NAME);
writeDDLToFiles(mgr, appLocation, createDDLJdbc, dropDDLJdbc, ddlType, props);
}
// Log a warning if we have an unknown ddl generation mode.
if ( (! ddlGenerationMode.equals(PersistenceUnitProperties.DDL_DATABASE_GENERATION)) && (! ddlGenerationMode.equals(PersistenceUnitProperties.DDL_SQL_SCRIPT_GENERATION)) && (! ddlGenerationMode.equals(PersistenceUnitProperties.DDL_BOTH_GENERATION))) {
String validOptions = PersistenceUnitProperties.DDL_DATABASE_GENERATION + ", " +
PersistenceUnitProperties.DDL_SQL_SCRIPT_GENERATION + ", " +
PersistenceUnitProperties.DDL_BOTH_GENERATION;
session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "ddl_generation_unknown_property_value", new Object[] {PersistenceUnitProperties.DDL_GENERATION_MODE, ddlGenerationMode, persistenceUnitInfo.getPersistenceUnitName(), validOptions});
}
if (isCompositeMember()) {
// debug output added to make it easier to navigate the log because the method is called outside of composite member deploy
session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_end_call", new Object[]{"generateDDL", persistenceUnitInfo.getPersistenceUnitName(), state});
}
}
}
}
/**
* INTERNAL:
* Generate the DDL per the properties given.
*/
protected void writeDDL(String generationSourceProperty, String scriptGenerationSourceProperty, TableCreationType tableCreationType, Map props, DatabaseSessionImpl session, ClassLoader loader) {
String generationSource = getConfigPropertyAsString(generationSourceProperty, props);
Object scriptGenerationSource = getConfigProperty(scriptGenerationSourceProperty, props);
if (generationSource == null) {
if (scriptGenerationSource == null) {
writeMetadataDDLToDatabase(tableCreationType, props, session, loader);
} else {
writeSourceScriptToDatabase(scriptGenerationSource, session, loader);
}
} else if (generationSource.equals(SCHEMA_GENERATION_METADATA_SOURCE)) {
writeMetadataDDLToDatabase(tableCreationType, props, session, loader);
} else if (generationSource.equals(SCHEMA_GENERATION_SCRIPT_SOURCE)) {
writeSourceScriptToDatabase(scriptGenerationSource, session, loader);
} else if (generationSource.equals(SCHEMA_GENERATION_METADATA_THEN_SCRIPT_SOURCE)) {
writeMetadataDDLToDatabase(tableCreationType, props, session, loader);
writeSourceScriptToDatabase(scriptGenerationSource, session, loader);
} else if (generationSource.equals(SCHEMA_GENERATION_SCRIPT_THEN_METADATA_SOURCE)) {
writeSourceScriptToDatabase(scriptGenerationSource, session, loader);
writeMetadataDDLToDatabase(tableCreationType, props, session, loader);
} else {
String validOptions = SCHEMA_GENERATION_METADATA_SOURCE + ", " +
SCHEMA_GENERATION_SCRIPT_SOURCE + ", " +
SCHEMA_GENERATION_METADATA_THEN_SCRIPT_SOURCE + ", " +
SCHEMA_GENERATION_SCRIPT_THEN_METADATA_SOURCE;
session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "ddl_generation_unknown_property_value", new Object[] {generationSourceProperty, generationSource, persistenceUnitInfo.getPersistenceUnitName(), validOptions});
}
}
/**
* INTERNAL:
* Generate and write DDL from the persistence unit metadata to the database.
*/
protected void writeDDLToDatabase(SchemaManager mgr, TableCreationType ddlType) {
String str = getConfigPropertyAsString(PersistenceUnitProperties.JAVASE_DB_INTERACTION, null ,"true");
boolean interactWithDB = Boolean.valueOf(str.toLowerCase()).booleanValue();
if (!interactWithDB){
return;
}
generateDefaultTables(mgr, ddlType);
}
/**
* @deprecated Extenders should now use
* {@link #writeDDLToFiles(SchemaManager, String, Object, Object, TableCreationType, Map)}
*/
@Deprecated
protected void writeDDLToFiles(SchemaManager mgr, String appLocation, Object createDDLJdbc, Object dropDDLJdbc,
TableCreationType ddlType) {
writeDDLToFiles(mgr, appLocation, createDDLJdbc, dropDDLJdbc, ddlType, Collections.EMPTY_MAP);
}
/**
* Write the DDL to the files provided.
*/
protected void writeDDLToFiles(SchemaManager mgr, String appLocation, Object createDDLJdbc, Object dropDDLJdbc, TableCreationType ddlType, Map props) {
// Ensure that the appLocation string ends with File.separator if
// specified. In JPA there is no default for app location, however, if
// the user did specify one, we'll use it.
String appLocationPrefix = (appLocation == null) ? "" : addFileSeperator(appLocation);
if (ddlType.equals(TableCreationType.CREATE) || ddlType.equals(TableCreationType.DROP_AND_CREATE) || ddlType.equals(TableCreationType.EXTEND)) {
if (createDDLJdbc == null) {
// Using EclipseLink properties, the create script has a default.
// Using JPA properties, the user must specify the target else an exception must be thrown.
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa21-ddl-create-script-target-not-specified"));
} else if (createDDLJdbc instanceof Writer) {
mgr.outputCreateDDLToWriter((Writer) createDDLJdbc);
} else {
// Assume it is a String file name.
mgr.outputCreateDDLToFile(appLocationPrefix + createDDLJdbc);
}
}
if (ddlType.equals(TableCreationType.DROP) || ddlType.equals(TableCreationType.DROP_AND_CREATE)) {
if (dropDDLJdbc == null) {
// Using EclipseLink properties, the drop script has a default.
// Using JPA properties, the user must specify the target else an exception must be thrown.
throw new IllegalArgumentException(ExceptionLocalization.buildMessage("jpa21-ddl-drop-script-target-not-specified"));
} else if (dropDDLJdbc instanceof Writer) {
mgr.outputDropDDLToWriter((Writer) dropDDLJdbc);
} else if (dropDDLJdbc instanceof String) {
mgr.outputDropDDLToFile(appLocationPrefix + dropDDLJdbc);
} else {
throw new PersistenceException(ExceptionLocalization.buildMessage("jpa21-ddl-invalid-target-script-type", new Object[]{ dropDDLJdbc , dropDDLJdbc.getClass()}));
}
}
String propString = getConfigPropertyAsString(PersistenceUnitProperties.SCHEMA_GENERATION_SCRIPT_TERMINATE_STATEMENTS, props);
boolean terminator = Boolean.parseBoolean(propString);
mgr.setCreateSQLFiles(terminator);
generateDefaultTables(mgr, ddlType);
mgr.closeDDLWriter();
}
/**
* INTERNAL:
* Generate and write DDL from the persistence unit metadata to the database.
*/
protected void writeMetadataDDLToDatabase(TableCreationType tableCreationType, Map props, DatabaseSessionImpl session, ClassLoader classLoader) {
SchemaManager mgr = new SchemaManager(session);
// Set the create database schemas flag on the schema manager.
String createSchemas = getConfigPropertyAsString(SCHEMA_GENERATION_CREATE_DATABASE_SCHEMAS, props);
mgr.setCreateDatabaseSchemas(createSchemas != null && createSchemas.equalsIgnoreCase("true"));
writeDDLToDatabase(mgr, tableCreationType);
}
/**
* INTERNAL:
* Generate and write DDL from the persistence unit metadata to scripts.
*/
protected void writeMetadataDDLToScript(TableCreationType tableCreationType, Map props, DatabaseSessionImpl session, ClassLoader classLoader) {
SchemaManager mgr = new SchemaManager(session);
// Set the create database schemas flag on the schema manager.
String createSchemas = getConfigPropertyAsString(SCHEMA_GENERATION_CREATE_DATABASE_SCHEMAS, props);
mgr.setCreateDatabaseSchemas(createSchemas != null && createSchemas.equalsIgnoreCase("true"));
writeDDLToFiles(mgr, getConfigPropertyAsString(PersistenceUnitProperties.APP_LOCATION, props), getConfigProperty(SCHEMA_GENERATION_SCRIPTS_CREATE_TARGET, props), getConfigProperty(SCHEMA_GENERATION_SCRIPTS_DROP_TARGET, props), tableCreationType, props);
}
/**
* This method will read SQL from a reader or URL and send it through
* to the database. This could open up the database to SQL injection if
* not careful.
*/
protected void writeSourceScriptToDatabase(Object source, DatabaseSessionImpl session, ClassLoader loader) {
if (source != null) {
Reader reader = null;
try {
if (source instanceof Reader) {
reader = (Reader) source;
} else if (source instanceof String) {
// Try to load the resource first, if not assume it as a well formed URL. If not, throw an exception.
URL sourceURL = loader.getResource((String) source);
if (sourceURL == null) {
try {
sourceURL = new URL((String) source);
} catch (MalformedURLException e) {
throw new PersistenceException(ExceptionLocalization.buildMessage("jpa21-ddl-source-script-not-found", new Object[]{ source }), e);
}
}
URLConnection connection = sourceURL.openConnection();
// Set to false to prevent locking of jar files on Windows. EclipseLink issue 249664
connection.setUseCaches(false);
reader = new InputStreamReader(connection.getInputStream(), "UTF-8");
} else {
throw new PersistenceException(ExceptionLocalization.buildMessage("jpa21-ddl-invalid-source-script-type", new Object[]{ source , source.getClass()}));
}
if (reader != null) {
StringBuffer sqlBuffer;
int data = reader.read();
// While there is still data to read, read line by line.
while (data != -1) {
sqlBuffer = new StringBuffer();
char aChar = (char) data;
// Read till the end of the line or maybe even file.
while (aChar != '\n' && data != -1) {
sqlBuffer.append(aChar);
// Read next character.
data = reader.read();
aChar = (char) data;
}
// Remove trailing and leading white space characters.
String sqlString = sqlBuffer.toString().trim();
// If the string isn't empty, then fire it.
if ((! sqlString.equals("")) && (! sqlString.startsWith("#"))) {
try {
session.executeNonSelectingSQL(sqlString);
} catch (DatabaseException e) {
// Swallow any database exceptions as these could
// be drop failures of a table that doesn't exist etc.
// SQLExceptions will be thrown to the user.
}
}
data = reader.read();
}
reader.close();
}
} catch (IOException e) {
throw new PersistenceException(ExceptionLocalization.buildMessage("jpa21-ddl-source-script-io-exception", new Object[]{source}), e);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
// ignore.
}
}
}
}
}
//JPA-RS feature may be provided by a jar on the path or missing
private static String shouldWeaveRestByDefault(ClassLoader cl) {
try {
cl.loadClass("org.eclipse.persistence.internal.jpa.rs.weaving.PersistenceWeavedRest");
return "true";
} catch (Throwable t) {
//ignore
}
return "false";
}
}