| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * Copyright (c) 1998, 2021 IBM Corporation. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| // |
| // 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.PropertiesUtils; |
| 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.databaseaccess.Platform; |
| 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.accessors.objects.MetadataClass; |
| 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<StructConverter> 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<EntityManagerSetupImpl> 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); |
| } |
| |
| final Platform platform = getDatabaseSession().getDatasourcePlatform(); |
| String dbProperties = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.TARGET_DATABASE_PROPERTIES, deployProperties, this.session); |
| PropertiesUtils.set(platform, PersistenceUnitProperties.TARGET_DATABASE_PROPERTIES, dbProperties); |
| |
| // 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. |
| * |
| */ |
| 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<Sequence> itProjectSequences = projectPlatform.getSequences().values().iterator(); |
| while (itProjectSequences.hasNext()) { |
| 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<String,Session> 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<ClassDescriptor> 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 = 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(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. |
| * |
| */ |
| protected List<StructConverter> getStructConverters(ClassLoader realClassLoader) { |
| List<StructConverter> structConverters = new ArrayList<StructConverter>(); |
| 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<ClassDescriptor> it = session.getDescriptors().values().iterator(); |
| while (it.hasNext() && (!typeMap.isEmpty() || !sizeMap.isEmpty() || !sharedMap.isEmpty())) { |
| ClassDescriptor descriptor = 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<String, Object> connectionsMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CONNECTION_POOL, properties, serverSession); |
| if (connectionsMap.isEmpty()) { |
| return; |
| } |
| for (Map.Entry<String, Object> 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); |
| } |
| 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<Void>() { |
| @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<MetadataClass> 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<MetadataClass> 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<Class<?>> iterator = session.getProject().getDescriptors().keySet().iterator(); iterator.hasNext(); ) { |
| persistenceClasses.add(factory.getMetadataClass(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.parseBoolean(prop)); |
| } |
| prop = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_SHARED_CACHE, m, session); |
| if (prop != null) { |
| policy.setShouldUseSharedCache(Boolean.parseBoolean(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)); |
| } |
| |
| 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 = 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 = 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. |
| * @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<SEPersistenceUnitInfo> 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<String, ClassDetails>()); |
| } |
| |
| // 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. |
| */ |
| 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 = 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<SEPersistenceUnitInfo> 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<SEPersistenceUnitInfo> 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<String, SEPersistenceUnitInfo> getCompositeMemberPuInfoMap(PersistenceUnitInfo puInfo, Map predeployProperties) { |
| Set<SEPersistenceUnitInfo> memeberPuInfoSet = PersistenceUnitProcessor.getPersistenceUnits(puInfo.getClassLoader(), predeployProperties, puInfo.getJarFileUrls()); |
| HashMap<String, SEPersistenceUnitInfo> 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<String, SEPersistenceUnitInfo> containedMemberPuInfoMap = getCompositeMemberPuInfoMap(memberPuInfo, memberPuInfo.getProperties()); |
| Iterator<Map.Entry<String, SEPersistenceUnitInfo>> it = containedMemberPuInfoMap.entrySet().iterator(); |
| while (it.hasNext()) { |
| Map.Entry<String, SEPersistenceUnitInfo> 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<SEPersistenceUnitInfo> 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) |
| */ |
| public EntityManagerSetupImpl refreshMetadata(Map properties){ |
| String sessionName = getSessionName(); |
| String uniqueName = getPersistenceUnitUniqueName(); |
| EntityManagerSetupImpl newSetupImpl = new EntityManagerSetupImpl(uniqueName, sessionName); |
| newSetupImpl.setIsInContainerMode(isInContainerMode); |
| newSetupImpl.enableWeaving = enableWeaving; |
| Map<Object, Object> 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.parseBoolean(str.toLowerCase()); |
| 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"; |
| } |
| } |
| |