All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.persistence.internal.jpa.EntityManagerSetupImpl Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2024 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
//     12/05/2023: Tomas Kraus
//       - New Jakarta Persistence 3.2 Features
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.config.PersistenceUnitProperties.SCHEMA_GENERATION_VERIFY_ACTION;
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.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
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.SchemaValidationException;
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.annotations.CacheIsolationType;
import org.eclipse.persistence.descriptors.DescriptorCustomizer;
import org.eclipse.persistence.config.ExclusiveConnectionMode;
import org.eclipse.persistence.config.LoggerType;
import org.eclipse.persistence.config.ParserType;
import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.config.ProfilerType;
import org.eclipse.persistence.config.RemoteProtocol;
import org.eclipse.persistence.sessions.SessionCustomizer;
import org.eclipse.persistence.config.SystemProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.MultitenantPolicy;
import org.eclipse.persistence.descriptors.SchemaPerMultitenantPolicy;
import org.eclipse.persistence.descriptors.TimestampLockingPolicy;
import org.eclipse.persistence.descriptors.partitioning.PartitioningPolicy;
import org.eclipse.persistence.dynamic.DynamicClassLoader;
import org.eclipse.persistence.eis.EISConnectionSpec;
import org.eclipse.persistence.eis.EISLogin;
import org.eclipse.persistence.eis.EISPlatform;
import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.EntityManagerSetupException;
import org.eclipse.persistence.exceptions.ExceptionHandler;
import org.eclipse.persistence.exceptions.IntegrityException;
import org.eclipse.persistence.exceptions.PersistenceUnitLoadingException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.internal.databaseaccess.BatchWritingMechanism;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy;
import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy.LockOnChange;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConcurrencyManager;
import org.eclipse.persistence.internal.helper.ConcurrencyUtil;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.JPAClassLoaderHolder;
import org.eclipse.persistence.internal.helper.JPAConversionManager;
import org.eclipse.persistence.internal.identitymaps.IdentityMap;
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.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.PrivilegedGetValueFromField;
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.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.schemaframework.TableValidationException;
import org.eclipse.persistence.tools.tuning.SafeModeTuner;
import org.eclipse.persistence.tools.tuning.SessionTuner;
import org.eclipse.persistence.tools.tuning.StandardTuner;

/**
 * INTERNAL:
 * This class handles deployment of a persistence unit.
 * In predeploy the meta-data is processed and weaver transformer is returned to allow weaving of the persistent classes.
 * In deploy the project and session are initialize and registered.
 */
public class EntityManagerSetupImpl implements MetadataRefreshListener {
    /*
     * Design Pattern in use: Builder pattern
     * EntityManagerSetupImpl, MetadataProcessor and MetadataProject
     * play the role of director, builder and product respectively.
     * See processORMetadata which is the factory method.
     *
     */

    // this name should uniquely identify the persistence unit
    protected String persistenceUnitUniqueName;
    // session name should uniquely identify the session
    protected String sessionName;

    private MetadataProcessor processor = null;
    /** Holds a reference to the weaver class transformer so it can be cleared after login. */
    private PersistenceWeaver weaver = null;
    protected PersistenceUnitInfo persistenceUnitInfo = null;
    // count a number of open factories that use this object.
    protected int factoryCount = 0;
    protected AbstractSession session = null;
    // true if predeploy called by createContainerEntityManagerFactory; false - createEntityManagerFactory
    protected boolean isInContainerMode = false;
    protected boolean isSessionLoadedFromSessionsXML=false;
    //project caching:
    protected ProjectCache projectCacheAccessor = null;
    protected boolean shouldBuildProject = true;
    // indicates whether weaving was used on the first run through predeploy (in STATE_INITIAL)
    protected Boolean enableWeaving = null;
    // indicates that classes have already been woven
    protected boolean isWeavingStatic = false;
    // used by static weaving
    protected StaticWeaveInfo staticWeaveInfo;
    protected SecurableObjectHolder securableObjectHolder = new SecurableObjectHolder();
    // used by deploy method
    protected ConcurrencyManager deployLock = new ConcurrencyManager();

    protected boolean requiresConnection;

    // 266912: Criteria API and Metamodel API (See Ch 5 of the JPA 2.0 Specification)
    /** Reference to the Metamodel for this deployment and session.
     * Please use the accessor and not the instance variable directly*/
    private Metamodel metaModel;

    protected List structConverters = null;
    // factoryCount==0; session==null
    public static final String STATE_INITIAL        = "Initial";

    // session != null
    public static final String STATE_PREDEPLOYED    = "Predeployed";

    // factoryCount>0; session != null; session stored in SessionManager
    // for compositeMember factoryCount is always 0; session is never stored in SessionBroker
    // the session has not yet connected for the first time or failed to connect for the first time
    public static final String STATE_HALF_DEPLOYED  = "HalfDeployed";

    // factoryCount>0; session != null; session stored in SessionManager
    // for compositeMember factoryCount is always 0; session is never stored in SessionBroker
    // the session has connected for the first time
    public static final String STATE_DEPLOYED       = "Deployed";

    // factoryCount==0; session==null
    public static final String STATE_PREDEPLOY_FAILED="PredeployFailed";

    // factoryCount>0; session != null
    // for compositeMember factoryCount is always 0
    public static final String STATE_DEPLOY_FAILED  = "DeployFailed";

    // factoryCount==0; session==null
    public static final String STATE_UNDEPLOYED     = "Undeployed";

    // factoryCount==0; session==null
    // only composite member persistence unit can be in this state
    public static final String STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER = "HalfPredeployedCompositeMember";

    /**
     *     Initial -----> HalfPredeployedCompositeMember -----> PredeployFailed
     *                    |        ^                   |
     *                    V------->|                   V
     *                                                Predeployed
     */
    protected String state = STATE_INITIAL;

    /**
     *     Initial -----------> PredeployFailed ---
     *           |                                |
     *           V                                |
     *         Predeployed ---> DeployFailed --   |
     *           |                            |   |
     *           V                            V   V
     *         HalfDeployed --> Deployed -> Undeployed
     *           |                            ^
     *           V                            |
     *         DeployFailed -------------------
     *
     */


    public static final String ERROR_LOADING_XML_FILE = "error_loading_xml_file";
    public static final String EXCEPTION_LOADING_ENTITY_CLASS = "exception_loading_entity_class";

    /*
     * Properties used to generate sessionName if none is provided.
     */
    public static String[] connectionPropertyNames = {
        PersistenceUnitProperties.TRANSACTION_TYPE,
        PersistenceUnitProperties.JTA_DATASOURCE,
        PersistenceUnitProperties.NON_JTA_DATASOURCE,
        PersistenceUnitProperties.JDBC_URL,
        PersistenceUnitProperties.JDBC_USER,
        PersistenceUnitProperties.NOSQL_CONNECTION_SPEC,
        PersistenceUnitProperties.NOSQL_CONNECTION_FACTORY,
        PersistenceUnitProperties.NOSQL_USER,
        PersistenceUnitProperties.JDBC_CONNECTOR
    };

    /*
     * Composite, not null only if it's a composite member.
     */
    protected EntityManagerSetupImpl compositeEmSetupImpl;

    /*
     * Composite members, not null only if it's a composite.
     */
    protected Set compositeMemberEmSetupImpls;

    /*
     * In HalfPredeployedCompositeMember predeploy method called several times,
     * each call uses mode, then updating it before returning.
     * So mode value could be viewed as a substate of HalfPredeployedCompositeMember state.
     * The mode is required for staging of processing OR metadata for composite members:
     * each processing stage should be completed for ALL composite members before
     * any one of then could proceed to the next processing stage.
     */
    PersistenceUnitProcessor.Mode mode;

    boolean throwExceptionOnFail;
    boolean weaveChangeTracking;
    boolean weaveLazy;
    boolean weaveEager;
    boolean weaveFetchGroups;
    boolean weaveInternal;
    boolean weaveRest;
    boolean weaveMappedSuperClass;

    /**
     * Used to indicate that an EntityManagerFactoryImpl based on this
     * EntityManagerSetupImpl has been refreshed.  This means this EntityManagerSetupImpl
     * will no longer be associated with new EntityManagerFactories
     */
    protected boolean isMetadataExpired = false;

    /**
     * Used to distinguish the various DDL options.
     * Verification option is not included, because it does not modify the database content.
     */
    protected enum TableCreationType {
        /** Specifies that database tables should not be created or dropped. */
        NONE,
        /** Specifies that database tables should be created. */
        CREATE,
        /** Specifies that database tables should be dropped. */
        DROP,
        /** Specifies that database tables should be dropped, then created. */
        DROP_AND_CREATE,
        /** Specifies that database tables should be created and if existing, missing columns will be added. */
        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.isEmpty()) {
            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.isEmpty()) {
                    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 IllegalStateException(EntityManagerSetupException.compositeMemberCannotBeUsedStandalone(this.persistenceUnitInfo.getPersistenceUnitName())); } throw new PersistenceException(EntityManagerSetupException.cannotDeployWithoutPredeploy(this.persistenceUnitInfo.getPersistenceUnitName(), this.state, this.persistenceException)); } // state is PREDEPLOYED or DEPLOYED this.session.log(SessionLog.FINEST, SessionLog.JPA, "deploy_begin", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), this.session.getName(), this.state, this.factoryCount}); ClassLoader classLoaderToUse = realClassLoader; if (additionalProperties.containsKey(PersistenceUnitProperties.CLASSLOADER)) { classLoaderToUse = (ClassLoader) additionalProperties.get(PersistenceUnitProperties.CLASSLOADER); } else if ((this.processor != null) && (this.processor.getProject() != null) && (this.processor.getProject().hasVirtualClasses()) && (this.state == STATE_PREDEPLOYED) && (!(classLoaderToUse instanceof DynamicClassLoader))) { classLoaderToUse = new DynamicClassLoader(classLoaderToUse); } // indicates whether session has failed to connect, determines whether HALF_DEPLOYED state should be kept in case of exception. boolean isLockAcquired = false; try { Map deployProperties = mergeMaps(additionalProperties, this.persistenceUnitInfo.getProperties()); updateTunerPreDeploy(deployProperties, classLoaderToUse); translateOldProperties(deployProperties, this.session); if (isComposite()) { updateCompositeMembersProperties(deployProperties); } if (this.state == STATE_PREDEPLOYED) { this.deployLock.acquire(); isLockAcquired = true; if (this.state == STATE_PREDEPLOYED) { if (this.shouldBuildProject && !this.isSessionLoadedFromSessionsXML) { if (isComposite()) { deployCompositeMembers(deployProperties, classLoaderToUse); } else { if (this.processor.getMetadataSource() != null) { Map metadataProperties = this.processor.getMetadataSource().getPropertyOverrides(deployProperties, classLoaderToUse, this.session.getSessionLog()); if (metadataProperties != null && !metadataProperties.isEmpty()) { translateOldProperties(metadataProperties, this.session); deployProperties = mergeMaps(metadataProperties, deployProperties); } } // listeners and queries require the real classes and are therefore built during deploy using the realClassLoader this.processor.setClassLoader(classLoaderToUse); this.processor.createDynamicClasses(); this.processor.addEntityListeners(); if (this.projectCacheAccessor != null) { //cache the project: this.projectCacheAccessor.storeProject(this.session.getProject(), deployProperties, this.session.getSessionLog()); } // The project is initially created using class names rather than classes. This call will make the conversion. // If the session was loaded from sessions.xml this will also convert the descriptor classes to the correct class loader. this.session.getProject().convertClassNamesToClasses(classLoaderToUse); if (!isCompositeMember()) { addBeanValidationListeners(deployProperties, classLoaderToUse); } // Process the customizers last. this.processor.processCustomizers(); } this.processor = null; } else { // The project is initially created using class names rather than classes. This call will make the conversion. // If the session was loaded from sessions.xml this will also convert the descriptor classes to the correct class loader. this.session.getProject().convertClassNamesToClasses(classLoaderToUse); if (!this.shouldBuildProject) { //process anything that might not have been serialized/cached in the project correctly: if (!isCompositeMember()) { addBeanValidationListeners(deployProperties, classLoaderToUse); } //process Descriptor customizers: processDescriptorsFromCachedProject(classLoaderToUse); } } finishProcessingDescriptorEvents(classLoaderToUse); this.structConverters = getStructConverters(classLoaderToUse); updateRemote(deployProperties, classLoaderToUse); initSession(); if (this.session.getIntegrityChecker().hasErrors()){ this.session.handleException(new IntegrityException(session.getIntegrityChecker())); } this.session.getDatasourcePlatform().getConversionManager().setLoader(classLoaderToUse); this.state = STATE_HALF_DEPLOYED; // keep deployLock } else { // state is HALF_DEPLOYED or DEPLOY_FAILED this.deployLock.release(); isLockAcquired = false; if (this.state == STATE_DEPLOY_FAILED) { // while this thread waited in STATE_PREDEPLOYED another thread attempted to deploy and failed. // Rethrow the cache PersistenceException, which caused STATE_DEPLOYED_FAILED. throw persistenceException; } } } // state is HALF_DEPLOYED or DEPLOYED if (!isCompositeMember()) { if (this.session.isDatabaseSession() && !((DatabaseSessionImpl)session).isLoggedIn()) { // If it's HALF_DEPLOYED then deployLock has been already acquired. if (!isLockAcquired) { this.deployLock.acquire(); isLockAcquired = true; } if (!((DatabaseSessionImpl)this.session).isLoggedIn()) { if (this.state == STATE_DEPLOY_FAILED) { // while this thread waited in STATE_HALF_DEPLOYED another thread attempted to connect the session and failed. // Rethrow the cache PersistenceException, which caused STATE_DEPLOYED_FAILED. throw persistenceException; } this.session.setProperties(deployProperties); updateSession(deployProperties, classLoaderToUse); if (isValidationOnly(deployProperties, false)) { /* * for 324213 we could add a session.loginAndDetectDatasource() call * before calling initializeDescriptors when validation-only is True * to avoid a native sequence exception on a generic DatabasePlatform * by auto-detecting the correct DB platform. * However, this would introduce a DB login when validation is on * - in opposition to the functionality of the property (to only validate) */ if (this.state == STATE_HALF_DEPLOYED) { getDatabaseSession().initializeDescriptors(); this.state = STATE_DEPLOYED; } } else { try { updateTunerDeploy(deployProperties, classLoaderToUse); updateFreeMemory(deployProperties); if (this.isSessionLoadedFromSessionsXML) { getDatabaseSession().login(); } else { login(getDatabaseSession(), deployProperties, requiresConnection); } // Make JTA integration throw JPA exceptions. if (this.session.hasExternalTransactionController()) { if (this.session.getExternalTransactionController().getExceptionHandler() == null) { this.session.getExternalTransactionController().setExceptionHandler(new ExceptionHandler() { @Override public Object handleException(RuntimeException exception) { if (exception instanceof org.eclipse.persistence.exceptions.OptimisticLockException) { throw new OptimisticLockException(exception); } else if (exception instanceof EclipseLinkException) { throw new PersistenceException(exception); } else { throw exception; } } }); } } this.state = STATE_DEPLOYED; } catch (Throwable loginException) { if (this.state == STATE_HALF_DEPLOYED) { if (this.session.isConnected()) { // session is connected, but postConnect has failed. // Likely this is caused by failure in initializeDescriptors: // either descriptor exception or by invalid named jpql query. // Cannot recover from that - the user has to fix the persistence unit and redeploy it. try { getDatabaseSession().logout(); } catch (Throwable logoutException) { // Ignore } this.state = STATE_DEPLOY_FAILED; } } throw loginException; } if (!this.isSessionLoadedFromSessionsXML) { addStructConverters(); } // Generate the DDL using the correct connection. writeDDL(deployProperties, getDatabaseSession(deployProperties), classLoaderToUse); } } // Initialize platform specific identity sequences. session.getDatasourcePlatform().initIdentitySequences(getDatabaseSession(), MetadataProject.DEFAULT_IDENTITY_GENERATOR); updateTunerPostDeploy(deployProperties, classLoaderToUse); this.deployLock.release(); isLockAcquired = false; } // 266912: Initialize the Metamodel, a login should have already occurred. try { this.getMetamodel(classLoaderToUse); } catch (Exception e) { this.session.log(SessionLog.FINEST, SessionLog.METAMODEL, "metamodel_init_failed", new Object[]{e.getMessage()}); } } // Clear the weaver's reference to meta-data information, as it is held by the class loader and will never gc. if (this.weaver != null) { this.weaver.clear(); this.weaver = null; } return this.session; } catch (Throwable exception) { // before releasing deployLock switch to the correct state if (this.state == STATE_PREDEPLOYED) { this.state = STATE_DEPLOY_FAILED; } PersistenceException persistenceEx; if (this.state == STATE_DEPLOY_FAILED) { if (exception == persistenceException) { persistenceEx = new PersistenceException(EntityManagerSetupException.cannotDeployWithoutPredeploy(this.persistenceUnitInfo.getPersistenceUnitName(), this.state, this.persistenceException)); } else { // before releasing deployLock cache the exception persistenceEx = createDeployFailedPersistenceException(exception); } } else { if (exception instanceof PersistenceException) { persistenceEx = (PersistenceException)exception; } else { persistenceEx = new PersistenceException(exception); } } if (isLockAcquired) { this.deployLock.release(); } this.session.logThrowable(SessionLog.SEVERE, SessionLog.EJB, exception); throw persistenceEx; } finally { this.session.log(SessionLog.FINEST, SessionLog.JPA, "deploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), this.session.getName(), this.state, this.factoryCount}); } } /** * INTERNAL: * This method is used to resolve Descriptor Customizers that might have been stored in the project * for JPA project caching. * */ private void processDescriptorsFromCachedProject(ClassLoader realClassLoader) throws ClassNotFoundException, PrivilegedActionException, IllegalAccessException, InstantiationException { for (ClassDescriptor descriptor: session.getProject().getDescriptors().values()) { //process customizers: if (descriptor.getDescriptorCustomizerClassName() != null) { Class listenerClass = findClass(descriptor.getDescriptorCustomizerClassName(), realClassLoader); DescriptorCustomizer customizer = (DescriptorCustomizer) buildObjectForClass(listenerClass, DescriptorCustomizer.class); try { customizer.customize(descriptor); } catch (Exception e) { session.getSessionLog().logThrowable(SessionLog.FINER, SessionLog.METADATA, e); } } } } /** * INTERNAL: * This method is used to resolve Descriptor Events processed earlier into EventHolders that now need to be * used to create the DescriptorEventListeners and added to the DescriptorEventManager * */ private void finishProcessingDescriptorEvents(ClassLoader realClassLoader) { for (ClassDescriptor descriptor: session.getProject().getDescriptors().values()) { if (descriptor.hasEventManager()) { descriptor.getEventManager().processDescriptorEventHolders(session, realClassLoader); } } } protected PersistenceException createDeployFailedPersistenceException(Throwable ex) { PersistenceException perEx = new PersistenceException(EntityManagerSetupException.deployFailed(persistenceUnitInfo.getPersistenceUnitName(), ex)); if (persistenceException == null) { persistenceException = perEx; } return perEx; } /** * Adds descriptors plus sequencing info found on the project to the session. */ protected void addProjectToSession(ServerSession session, Project project) { DatasourcePlatform sessionPlatform = (DatasourcePlatform)session.getDatasourceLogin().getDatasourcePlatform(); DatasourcePlatform projectPlatform = (DatasourcePlatform)project.getDatasourceLogin().getDatasourcePlatform(); if (!sessionPlatform.hasDefaultSequence() && projectPlatform.hasDefaultSequence()) { sessionPlatform.setDefaultSequence(projectPlatform.getDefaultSequence()); } if ((sessionPlatform.getSequences() == null) || sessionPlatform.getSequences().isEmpty()) { if ((projectPlatform.getSequences() != null) && !projectPlatform.getSequences().isEmpty()) { sessionPlatform.setSequences(projectPlatform.getSequences()); } } else { if ((projectPlatform.getSequences() != null) && !projectPlatform.getSequences().isEmpty()) { Iterator itProjectSequences = projectPlatform.getSequences().values().iterator(); while (itProjectSequences.hasNext()) { Sequence sequence = itProjectSequences.next(); if (!sessionPlatform.getSequences().containsKey(sequence.getName())) { sessionPlatform.addSequence(sequence); } } } } session.addDescriptors(project); } /** * Put the given session into the session manager so it can be looked up later */ protected void addSessionToGlobalSessionManager() { SessionManager sm = SessionManager.getManager(); ConcurrentMap sessions = sm.getSessions(); AbstractSession oldSession = (AbstractSession) sessions.get(session.getName()); if(oldSession != null) { throw new PersistenceException(EntityManagerSetupException.attemptedRedeployWithoutClose(session.getName())); } sm.addSession(session); } /** * Add the StructConverters that were specified by annotation on the DatabasePlatform * This method must be called after the DatabasePlatform has been detected */ public void addStructConverters(){ if (this.compositeMemberEmSetupImpls == null) { for (StructConverter structConverter : structConverters){ if (session.getPlatform().getTypeConverters().get(structConverter.getJavaType()) != null){ throw ValidationException.twoStructConvertersAddedForSameClass(structConverter.getJavaType().getName()); } session.getPlatform().addStructConverter(structConverter); } } else { // composite for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) { if (!compositeMemberEmSetupImpl.structConverters.isEmpty()) { String compositeMemberPuName = compositeMemberEmSetupImpl.getPersistenceUnitInfo().getPersistenceUnitName(); // debug output added to make it easier to navigate the log because the method is called outside of composite member deploy compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_begin_call", new Object[]{"addStructConverters", compositeMemberPuName, state}); compositeMemberEmSetupImpl.addStructConverters(); compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_end_call", new Object[]{"addStructConverters", compositeMemberPuName, state}); } } } } /** * Assign a CMP3Policy to each descriptor, and sets the OptimisticLockingPolicy's LockOnChangeMode if applicable. */ protected void assignCMP3Policy() { // all descriptors assigned CMP3Policy Project project = session.getProject(); for (Iterator iterator = project.getDescriptors().values().iterator(); iterator.hasNext();){ //bug:4406101 changed class cast to base class, which is used in projects generated from 904 xml ClassDescriptor descriptor = 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((Class) cls); } } else { // originalServerPlatform is not custom - need a new one. serverPlatform = new CustomServerPlatform(getDatabaseSession()); serverPlatform.setExternalTransactionControllerClass((Class) 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) { DataPartitioningCallback callback = null; try { Class cls = findClassForProperty(callbackClassName, PersistenceUnitProperties.PARTITIONING_CALLBACK, loader); Constructor constructor = cls.getConstructor(); callback = 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 { try { Class cls = findClassForProperty(protocol, PersistenceUnitProperties.REMOTE_PROTOCOL, loader); Constructor constructor = cls.getConstructor(); connection = 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); } // 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"; } DatabaseEventListener listener = null; try { Class cls = findClassForProperty(listenerClassName, PersistenceUnitProperties.DATABASE_EVENT_LISTENER, loader); Constructor constructor = cls.getConstructor(); listener = 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. try { Class sessionLogClass = findClassForProperty(loggerClassName, PersistenceUnitProperties.LOGGING_LOGGER, loader); singletonLog = sessionLogClass.getConstructor().newInstance(); 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().isEmpty()) { 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 | InstantiationException | PrivilegedActionException 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); } } @SuppressWarnings({"unchecked"}) private static Class findClassForPropertyInternal(String clsName, String propName, ClassLoader... loaders) { RuntimeException e = null; for (ClassLoader loader : loaders) { try { return (Class) 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 getStructConverters(ClassLoader realClassLoader) { List structConverters = new ArrayList<>(); if (session.getProject().getStructConverters() != null) { for (String converter: session.getProject().getStructConverters()) { Class clazz = null; try { clazz = findClass(converter, realClassLoader); } catch (PrivilegedActionException exception) { throw ValidationException.unableToLoadClass(converter, exception.getException()); } catch (ClassNotFoundException exception) { throw ValidationException.unableToLoadClass(converter, exception); } try { structConverters.add((StructConverter) buildObjectForClass(clazz, StructConverter.class)); } catch (PrivilegedActionException e) { throw ValidationException.errorInstantiatingClass(clazz, e.getException()); } catch (IllegalAccessException | InstantiationException e) { throw ValidationException.errorInstantiatingClass(clazz, e); } } } return structConverters; } protected boolean hasSchemaDatabaseGeneration(Map m) { if (hasConfigProperty(SCHEMA_GENERATION_DATABASE_ACTION, m)) { return getConfigPropertyAsString(SCHEMA_GENERATION_DATABASE_ACTION, m) != null && ! getConfigPropertyAsString(SCHEMA_GENERATION_DATABASE_ACTION, m).equals(SCHEMA_GENERATION_NONE_ACTION); } return false; } protected boolean hasSchemaScriptsGeneration(Map m) { if (hasConfigProperty(SCHEMA_GENERATION_SCRIPTS_ACTION, m)) { return getConfigPropertyAsString(SCHEMA_GENERATION_SCRIPTS_ACTION, m) != null && ! getConfigPropertyAsString(SCHEMA_GENERATION_SCRIPTS_ACTION, m).equals(SCHEMA_GENERATION_NONE_ACTION); } return false; } public AbstractSession getSession() { return session; } public DatabaseSessionImpl getDatabaseSession() { return (DatabaseSessionImpl)session; } /** * We may be provided a connection via the properties to use. Check for * one and build a database session around it. Otherwise return the pu * database session. */ public DatabaseSessionImpl getDatabaseSession(Map props) { DatabaseSessionImpl databaseSession = getDatabaseSession(); Object connection = getConfigProperty(PersistenceUnitProperties.SCHEMA_GENERATION_CONNECTION, props); if (connection == null) { return databaseSession; } else { // A connection was provided. Build a database session using that // connection and use the same log level set on the original // database session. DatabaseSessionImpl newDatabaseSession = new DatabaseSessionImpl(); newDatabaseSession.setAccessor(new DatabaseAccessor(connection)); newDatabaseSession.setLogLevel(databaseSession.getLogLevel()); newDatabaseSession.setProject(databaseSession.getProject().clone()); return newDatabaseSession; } } /** * This method will be used to validate the specified class and return it's instance. */ protected static Object buildObjectForClass(Class clazz, Class mustBeImplementedInterface) throws IllegalAccessException, PrivilegedActionException,InstantiationException { if(clazz!=null && Helper.classImplementsInterface(clazz,mustBeImplementedInterface)){ if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ return AccessController.doPrivileged(new PrivilegedNewInstanceFromClass(clazz)); } else { return PrivilegedAccessHelper.newInstanceFromClass(clazz); } } else { return null; } } protected void updateDescriptorCacheSettings(Map m, ClassLoader loader) { String queryCache = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.QUERY_CACHE, m, session); if ((queryCache != null) && queryCache.equalsIgnoreCase("true")) { session.getProject().setDefaultQueryResultsCachePolicy(new QueryResultsCachePolicy()); } String queryCacheForceDeferredLocks = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.CACHE_QUERY_FORCE_DEFERRED_LOCKS, m, session); if ((queryCacheForceDeferredLocks != null) && queryCacheForceDeferredLocks.equalsIgnoreCase("true")) { session.getProject().setQueryCacheForceDeferredLocks(true); } else { session.getProject().setQueryCacheForceDeferredLocks(false); } Map typeMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CACHE_TYPE_, m, session); Map sizeMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CACHE_SIZE_, m, session); Map sharedMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CACHE_SHARED_, m, session); if(typeMap.isEmpty() && sizeMap.isEmpty() && sharedMap.isEmpty()) { return; } String defaultTypeName = (String)typeMap.remove(PersistenceUnitProperties.DEFAULT); if (defaultTypeName != null) { // Always use the EclipseLink class loader, otherwise can have loader/redeployment issues. Class defaultType = findClassForProperty(defaultTypeName, PersistenceUnitProperties.CACHE_TYPE_DEFAULT, getClass().getClassLoader()); session.getProject().setDefaultIdentityMapClass(defaultType); } String value = null; try { String defaultSizeString = (String)sizeMap.remove(PersistenceUnitProperties.DEFAULT); if (defaultSizeString != null) { value = defaultSizeString; int defaultSize = Integer.parseInt(defaultSizeString); session.getProject().setDefaultIdentityMapSize(defaultSize); } String defaultSharedString = (String)sharedMap.remove(PersistenceUnitProperties.DEFAULT); if (defaultSharedString != null) { boolean defaultShared = Boolean.parseBoolean(defaultSharedString); session.getProject().setDefaultCacheIsolation(defaultShared ? CacheIsolationType.SHARED : CacheIsolationType.ISOLATED); } Iterator it = session.getDescriptors().values().iterator(); while (it.hasNext() && (!typeMap.isEmpty() || !sizeMap.isEmpty() || !sharedMap.isEmpty())) { ClassDescriptor descriptor = it.next(); if (descriptor.isDescriptorTypeAggregate()) { continue; } String entityName = descriptor.getAlias(); String className = descriptor.getJavaClass().getName(); String name; name = entityName; String typeName = (String)typeMap.remove(name); if( typeName == null) { name = className; typeName = (String)typeMap.remove(name); } if (typeName != null) { Class type = findClassForProperty(typeName, PersistenceUnitProperties.CACHE_TYPE_ + name, getClass().getClassLoader()); descriptor.setIdentityMapClass(type); } name = entityName; String sizeString = (String)sizeMap.remove(name); if (sizeString == null) { name = className; sizeString = (String)sizeMap.remove(name); } if (sizeString != null) { value = sizeString; int size = Integer.parseInt(sizeString); descriptor.setIdentityMapSize(size); } name = entityName; String sharedString = (String)sharedMap.remove(name); if (sharedString == null) { name = className; sharedString = (String)sharedMap.remove(name); } if (sharedString != null) { boolean shared = Boolean.parseBoolean(sharedString); descriptor.setCacheIsolation(shared ? CacheIsolationType.SHARED : CacheIsolationType.ISOLATED); } } } catch (NumberFormatException exception) { this.session.handleException(ValidationException.invalidValueForProperty(value, PersistenceUnitProperties.CACHE_SIZE_, exception)); } } /** * Process all properties under "eclipselink.connection-pool.". * This allows for named connection pools. * It also processes "read", "write", "default" and "sequence" connection pools. */ protected void updateConnectionSettings(ServerSession serverSession, Map properties) { Map connectionsMap = PropertiesHandler.getPrefixValuesLogDebug(PersistenceUnitProperties.CONNECTION_POOL, properties, serverSession); if (connectionsMap.isEmpty()) { return; } for (Map.Entry entry : connectionsMap.entrySet()) { String poolName = "default"; String attribute = null; try { int dotIdx = entry.getKey().indexOf('.'); if (dotIdx == -1) { attribute = entry.getKey(); } else { String key = entry.getKey(); poolName = key.substring(0, dotIdx); attribute = key.substring(dotIdx + 1); } 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 IllegalStateException(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.isEmpty()) { transactionType=PersistenceUnitTransactionType.valueOf(transTypeString); } else if (persistenceUnitInfo!=null){ transactionType=persistenceUnitInfo.getTransactionType(); } if (!isValidationOnly(predeployProperties, false) && persistenceUnitInfo != null && transactionType == PersistenceUnitTransactionType.JTA) { if (predeployProperties.get(PersistenceUnitProperties.JTA_DATASOURCE) == null && persistenceUnitInfo.getJtaDataSource() == null) { if (predeployProperties.get(PersistenceUnitProperties.SCHEMA_DATABASE_PRODUCT_NAME) == null || predeployProperties.get(PersistenceUnitProperties.SCHEMA_DATABASE_MAJOR_VERSION) == null || predeployProperties.get(PersistenceUnitProperties.SCHEMA_DATABASE_MINOR_VERSION) == null) { throw EntityManagerSetupException.jtaPersistenceUnitInfoMissingJtaDataSource(persistenceUnitInfo.getPersistenceUnitName()); } } } } // this flag is used to disable work done as a result of the LAZY hint on OneToOne and ManyToOne mappings if(state == STATE_INITIAL) { if (compositeEmSetupImpl == null) { if(null == enableWeaving) { enableWeaving = Boolean.TRUE; } isWeavingStatic = false; String weaving = getConfigPropertyAsString(PersistenceUnitProperties.WEAVING, predeployProperties); if (weaving != null && weaving.equalsIgnoreCase("false")) { enableWeaving = Boolean.FALSE; }else if (weaving != null && weaving.equalsIgnoreCase("static")) { isWeavingStatic = true; } } else { // composite member // no weaving for composite forces no weaving for members if (!compositeEmSetupImpl.enableWeaving) { enableWeaving = Boolean.FALSE; } else { if(null == enableWeaving) { enableWeaving = Boolean.TRUE; } String weaving = getConfigPropertyAsString(PersistenceUnitProperties.WEAVING, predeployProperties); if (weaving != null && weaving.equalsIgnoreCase("false")) { enableWeaving = Boolean.FALSE; } } // static weaving is dictated by composite isWeavingStatic = compositeEmSetupImpl.isWeavingStatic; } } if (compositeEmSetupImpl == null) { throwExceptionOnFail = "true".equalsIgnoreCase( EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.THROW_EXCEPTIONS, predeployProperties, "true", session)); } else { // composite member throwExceptionOnFail = compositeEmSetupImpl.throwExceptionOnFail; } } else { // predeploy is used for static weaving enableWeaving = Boolean.TRUE; } weaveChangeTracking = false; weaveLazy = false; weaveEager = false; weaveFetchGroups = false; weaveInternal = false; weaveRest = false; weaveMappedSuperClass = false; if (enableWeaving) { weaveChangeTracking = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_CHANGE_TRACKING, predeployProperties, "true", session)); weaveLazy = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_LAZY, predeployProperties, "true", session)); weaveEager = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_EAGER, predeployProperties, "false", session)); weaveFetchGroups = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_FETCHGROUPS, predeployProperties, "true", session)); weaveInternal = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_INTERNAL, predeployProperties, "true", session)); weaveRest = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_REST, predeployProperties, shouldWeaveRestByDefault(classLoaderToUse), session)); weaveMappedSuperClass = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.WEAVING_MAPPEDSUPERCLASS, predeployProperties, "true", session)); } } if (shouldBuildProject && !isSessionLoadedFromSessionsXML ) { if (isComposite) { predeployCompositeMembers(predeployProperties, classLoaderToUse); } else { MetadataProcessor compositeProcessor = null; if (compositeEmSetupImpl == null) { mode = PersistenceUnitProcessor.Mode.ALL; } else { // composite member if (state != STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER) { state = STATE_HALF_PREDEPLOYED_COMPOSITE_MEMBER; mode = PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL; } compositeProcessor = compositeEmSetupImpl.processor; } if (mode == PersistenceUnitProcessor.Mode.ALL || mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL) { boolean usesMultitenantSharedEmf = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, predeployProperties, "true", session)); boolean usesMultitenantSharedCache = "true".equalsIgnoreCase(EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.MULTITENANT_SHARED_CACHE, predeployProperties, "false", session)); // Create an instance of MetadataProcessor for specified persistence unit info processor = new MetadataProcessor(persistenceUnitInfo, session, classLoaderToUse, weaveLazy, weaveEager, weaveFetchGroups, usesMultitenantSharedEmf, usesMultitenantSharedCache, predeployProperties, compositeProcessor); //need to use the real classloader to create the repository class updateMetadataRepository(predeployProperties, classLoaderToUse); //bug:299926 - Case insensitive table / column matching with native SQL queries EntityManagerSetupImpl.updateCaseSensitivitySettings(predeployProperties, processor.getProject(), session); } // Set the shared cache mode to the jakarta.persistence.sharedCache.mode property value. updateSharedCacheMode(predeployProperties); // Process the Object/relational metadata from XML and annotations. // If Java Security is enabled, surround this call with a doPrivileged block. if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) { AccessController.doPrivileged(new PrivilegedAction() { @Override public Void run() { PersistenceUnitProcessor.processORMetadata(processor, throwExceptionOnFail, mode); return null; } }); } else { PersistenceUnitProcessor.processORMetadata(processor, throwExceptionOnFail, mode); } if (mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_INITIAL) { mode = PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_MIDDLE; session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state + " " + mode , factoryCount}); return null; } else if (mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_MIDDLE) { mode = PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_FINAL; session.log(SessionLog.FINEST, SessionLog.JPA, "predeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), session.getName(), state + " " + mode , factoryCount}); return null; } // mode == PersistenceUnitProcessor.Mode.ALL || mode == PersistenceUnitProcessor.Mode.COMPOSITE_MEMBER_FINAL // clear mode and proceed mode = null; if (session.getIntegrityChecker().hasErrors()){ session.handleException(new IntegrityException(session.getIntegrityChecker())); } // The transformer is capable of altering domain classes to handle a LAZY hint for OneToOne mappings. It will only // be returned if we we are mean to process these mappings if (enableWeaving) { // build a list of entities the persistence unit represented by this EntityManagerSetupImpl will use Collection entities = PersistenceUnitProcessor.buildEntityList(processor, classLoaderToUse); this.weaver = TransformerFactory.createTransformerAndModifyProject(session, entities, classLoaderToUse, weaveLazy, weaveChangeTracking, weaveFetchGroups, weaveInternal, weaveRest, weaveMappedSuperClass); session.getProject().setClassNamesForWeaving(new ArrayList<>(processor.getProject().getWeavableClassNames())); } //moved from deployment: processor.addNamedQueries(); processor.addStructConverterNames(); } } else { //This means this session is from sessions.xml or a cached project // The transformer is capable of altering domain classes to handle a LAZY hint for OneToOne mappings. It will only // be returned if we we are meant to process these mappings. if (enableWeaving) { Collection persistenceClasses = new ArrayList<>(); MetadataAsmFactory factory = new MetadataAsmFactory(new MetadataLogger(session), classLoaderToUse); if (shouldBuildProject) { // If deploying from a sessions-xml it is still desirable to allow the classes to be weaved. // build a list of entities the persistence unit represented by this EntityManagerSetupImpl will use for (Iterator> iterator = session.getProject().getDescriptors().keySet().iterator(); iterator.hasNext(); ) { persistenceClasses.add(factory.getMetadataClass(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(System.lineSeparator()); } 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)) { rcm.setTransportManager(TransportManager.newTransportManager("org.eclipse.persistence.sessions.remote.rmi.iiop.RMIIIOPTransportManager", rcm)); } // 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.isEmpty()) { 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 = 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) { Connector connector = null; try { 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()); } Constructor constructor = cls.getConstructor(); 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); } String encryptionClassName = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.LOGIN_ENCRYPTOR, m, this.session); if (encryptionClassName != null) { this.securableObjectHolder.setEncryptionClassName(encryptionClassName); login.setEncryptionClassName(encryptionClassName); } // 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.isEmpty()) { 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).isEmpty()) { // Create a dummy DataSource that will throw an exception on access return new DataSourceImpl((String)datasource, null, null, null); } else { // allow an empty string data source property passed to createEMF to cancel data source specified in persistence.xml return null; } } if ( !(datasource instanceof javax.sql.DataSource) ){ //A warning should be enough. Though an error might be better, the properties passed in could contain anything session.log(SessionLog.WARNING, SessionLog.PROPERTIES, "invalid_datasource_property_value", property, datasource); return defaultDataSource; } return (javax.sql.DataSource)datasource; } /** * In cases where there is no data source, we will use properties to configure the login for * our session. This method gets those properties and sets them on the login. */ protected void updateLoginDefaultConnector(DatasourceLogin login, Map m){ //Login info might be already set with sessions.xml and could be overridden by session customizer after this //If login has default connector then JDBC properties update(override) the login info if ((login.getConnector() instanceof DefaultConnector)) { DatabaseLogin dbLogin = (DatabaseLogin)login; // Note: This call does not checked the stored persistenceUnitInfo or extended properties because // the map passed into this method should represent the full set of properties we expect to process String jdbcDriver = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_DRIVER, m, session); String connectionString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_URL, m, session); if(connectionString != null) { dbLogin.setConnectionString(connectionString); } if(jdbcDriver != null) { dbLogin.setDriverClassName(jdbcDriver); } } } /** * Configure the internal connection pooling parameters. * By default if nothing is configured a default shared (exclusive) read/write pool is used with 32 min/max connections and 1 initial. */ @SuppressWarnings("deprecation") protected void updatePools(ServerSession serverSession, Map m) { String value = null; String property = null; try { // Configure default/write connection pool. // Sizes are irrelevant for external connection pool if (!serverSession.getDefaultConnectionPool().getLogin().shouldUseExternalConnectionPooling()) { // CONNECTION and WRITE_CONNECTION properties both configure the default pool (mean the same thing, but WRITE normally used with READ). property = PersistenceUnitProperties.JDBC_CONNECTIONS_MIN; value = getConfigPropertyAsStringLogDebug(property, m, serverSession); if (value != null) { serverSession.getDefaultConnectionPool().setMinNumberOfConnections(Integer.parseInt(value)); } property = PersistenceUnitProperties.JDBC_CONNECTIONS_MAX; value = getConfigPropertyAsStringLogDebug(property, m, serverSession); if (value != null) { serverSession.getDefaultConnectionPool().setMaxNumberOfConnections(Integer.parseInt(value)); } property = PersistenceUnitProperties.JDBC_CONNECTIONS_INITIAL; value = getConfigPropertyAsStringLogDebug(property, m, serverSession); if (value != null) { serverSession.getDefaultConnectionPool().setInitialNumberOfConnections(Integer.parseInt(value)); } property = PersistenceUnitProperties.JDBC_WRITE_CONNECTIONS_MIN; value = getConfigPropertyAsStringLogDebug(property, m, serverSession); if (value != null) { serverSession.getDefaultConnectionPool().setMinNumberOfConnections(Integer.parseInt(value)); } property = PersistenceUnitProperties.JDBC_WRITE_CONNECTIONS_MAX; value = getConfigPropertyAsStringLogDebug(property, m, serverSession); if (value != null) { serverSession.getDefaultConnectionPool().setMaxNumberOfConnections(Integer.parseInt(value)); } property = PersistenceUnitProperties.JDBC_WRITE_CONNECTIONS_INITIAL; value = getConfigPropertyAsStringLogDebug(property, m, serverSession); if (value != null) { serverSession.getDefaultConnectionPool().setInitialNumberOfConnections(Integer.parseInt(value)); } } // Configure read connection pool if set. // Sizes and shared option are irrelevant for external connection pool if (!serverSession.getReadConnectionPool().getLogin().shouldUseExternalConnectionPooling()) { String shared = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_SHARED, m, serverSession); boolean isShared = false; if (shared != null) { isShared = Boolean.parseBoolean(shared); } ConnectionPool pool = null; if (isShared) { pool = new ReadConnectionPool("read", serverSession.getReadConnectionPool().getLogin(), serverSession); } else { pool = new ConnectionPool("read", serverSession.getReadConnectionPool().getLogin(), serverSession); } String min = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MIN, m, serverSession); if (min != null) { value = min; property = PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MIN; pool.setMinNumberOfConnections(Integer.parseInt(min)); } String max = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MAX, m, serverSession); if (max != null) { value = max; property = PersistenceUnitProperties.JDBC_READ_CONNECTIONS_MAX; pool.setMaxNumberOfConnections(Integer.parseInt(max)); } String initial = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_READ_CONNECTIONS_INITIAL, m, serverSession); if (initial != null) { value = initial; property = PersistenceUnitProperties.JDBC_READ_CONNECTIONS_INITIAL; pool.setInitialNumberOfConnections(Integer.parseInt(initial)); } // Only set the read pool if they configured it, otherwise use default shared read/write. if (isShared || (min != null) || (max != null) || (initial != null)) { serverSession.setReadConnectionPool(pool); } String wait = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_CONNECTIONS_WAIT, m, serverSession); if (wait != null) { value = wait; property = PersistenceUnitProperties.JDBC_CONNECTIONS_WAIT; serverSession.getDefaultConnectionPool().setWaitTimeout(Integer.parseInt(wait)); pool.setWaitTimeout(Integer.parseInt(wait)); } } // Configure sequence connection pool if set. String sequence = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL, m, serverSession); if (sequence != null) { serverSession.getSequencingControl().setShouldUseSeparateConnection(Boolean.parseBoolean(sequence)); } String sequenceDataSource = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_DATASOURCE, m, serverSession); if (sequenceDataSource != null) { DatasourceLogin login = this.session.getLogin().clone(); login.dontUseExternalTransactionController(); JNDIConnector jndiConnector = new JNDIConnector(sequenceDataSource); login.setConnector(jndiConnector); serverSession.getSequencingControl().setLogin(login); } // Sizes and shared option are irrelevant for external connection pool if (!serverSession.getReadConnectionPool().getLogin().shouldUseExternalConnectionPooling()) { value = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MIN, m, serverSession); if (value != null) { property = PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MIN; serverSession.getSequencingControl().setMinPoolSize(Integer.parseInt(value)); } value = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MAX, m, serverSession); if (value != null) { property = PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_MAX; serverSession.getSequencingControl().setMaxPoolSize(Integer.parseInt(value)); } value = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_INITIAL, m, serverSession); if (value != null) { property = PersistenceUnitProperties.JDBC_SEQUENCE_CONNECTION_POOL_INITIAL; serverSession.getSequencingControl().setInitialPoolSize(Integer.parseInt(value)); } } } catch (NumberFormatException exception) { serverSession.handleException(ValidationException.invalidValueForProperty(value, property, exception)); } } /** * Normally when a property is missing nothing should be applied to the session. * However there are several session attributes that defaulted in EJB3 to the values * different from EclipseLink defaults. * This function applies defaults for such properties and registers the session. * All other session-related properties are applied in updateServerSession. * Note that updateSession may be called several times on the same session * (before login), but initSession is called just once - before the first call * to updateSession. */ protected void initSession() { assignCMP3Policy(); if(!isCompositeMember()) { // Register session that has been created earlier. addSessionToGlobalSessionManager(); } } /** * Make any changes to our ServerSession that can be made after it is created. */ protected void updateSession(Map m, ClassLoader loader) { if (session == null || (session.isDatabaseSession() && ((DatabaseSessionImpl)session).isLoggedIn())) { return; } // In deploy ServerPlatform could've changed which will affect the loggers. boolean serverPlatformChanged = updateServerPlatform(m, loader); updateJPQLParser(m); if (!session.hasBroker()) { updateLoggers(m, serverPlatformChanged, loader); updateProfiler(m,loader); } // log the server platform being used by the session if it has been changed if (serverPlatformChanged && session.getSessionLog().shouldLog(SessionLog.FINE)) { session.getSessionLog().log(SessionLog.FINE, SessionLog.SERVER, "configured_server_platform", session.getServerPlatform().getClass().getName()); // NOI18N } if(session.isBroker()) { PersistenceUnitTransactionType transactionType = persistenceUnitInfo.getTransactionType(); //bug 5867753: find and override the transaction type using properties String transTypeString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.TRANSACTION_TYPE, m, session); if (transTypeString != null) { transactionType = PersistenceUnitTransactionType.valueOf(transTypeString); } ((DatasourceLogin)session.getDatasourceLogin()).setUsesExternalTransactionController(transactionType == PersistenceUnitTransactionType.JTA); } else { String shouldBindString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_BIND_PARAMETERS, m, session); if (shouldBindString != null) { session.getPlatform().setShouldBindAllParameters(Boolean.parseBoolean(shouldBindString)); } String shouldForceBindString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_FORCE_BIND_PARAMETERS, m, session); if(shouldForceBindString != null) { session.getPlatform().setShouldForceBindAllParameters(Boolean.parseBoolean(shouldForceBindString)); } String allowPartialBindString = getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.JDBC_ALLOW_PARTIAL_PARAMETERS, m, session); if(allowPartialBindString != null) { session.getPlatform().setShouldBindPartialParameters(Boolean.parseBoolean(allowPartialBindString)); } updateLogins(m); } if (!session.getDatasourceLogin().shouldUseExternalTransactionController()) { session.getServerPlatform().disableJTA(); } if(session.isServerSession()) { updatePools((ServerSession)session, m); updateConnectionSettings((ServerSession)session, m); if (!isSessionLoadedFromSessionsXML) { updateDescriptorCacheSettings(m, loader); } updateConnectionPolicy((ServerSession)session, m); } if(session.isBroker()) { if (this.compositeMemberEmSetupImpls != null) { // composite Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, m); for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) { // the properties guaranteed to be non-null after updateCompositeMemberProperties call String compositeMemberPuName = compositeMemberEmSetupImpl.getPersistenceUnitInfo().getPersistenceUnitName(); Map compositeMemberProperties = (Map)compositeMemberMapOfProperties.get(compositeMemberPuName); // debug output added to make it easier to navigate the log because the method is called outside of composite member deploy compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_begin_call", new Object[]{"updateSession", compositeMemberPuName, state}); compositeMemberEmSetupImpl.updateSession(compositeMemberProperties, loader); compositeMemberEmSetupImpl.session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "composite_member_end_call", new Object[]{"updateSession", compositeMemberPuName, state}); } } setSessionEventListener(m, loader); setExceptionHandler(m, loader); updateAllowZeroIdSetting(m); updateCacheCoordination(m, loader); processSessionCustomizer(m, loader); } else { setSessionEventListener(m, loader); setExceptionHandler(m, loader); updateBatchWritingSetting(m, loader); updateNativeSQLSetting(m); updateSequencing(m); updateSequencingStart(m); updateAllowNativeSQLQueriesSetting(m); updateSQLCastSetting(m); updateUppercaseSetting(m); updateCacheStatementSettings(m); updateAllowExtendedCacheLogging(m); updateAllowExtendedThreadLogging(m); updateAllowExtendedThreadLoggingThreadDump(m); updateAllowQueryResultsCacheValidation(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) { try { Class sessionCustomizerClass = findClassForProperty((String) customizer, PersistenceUnitProperties.SESSION_CUSTOMIZER, loader); 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) { try { Class customizerClass = findClassForProperty(customizerClassName, PersistenceUnitProperties.DESCRIPTOR_CUSTOMIZER_ + name, loader); DescriptorCustomizer customizer = 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){ try { Class sessionEventListenerClass = findClassForProperty(sessionEventListenerClassName,PersistenceUnitProperties.SESSION_EVENT_LISTENER_CLASS, loader); SessionEventListener sessionEventListener = (SessionEventListener)buildObjectForClass(sessionEventListenerClass, SessionEventListener.class); if(sessionEventListener!=null){ session.getEventManager().addListener(sessionEventListener); } else { session.handleException(ValidationException.invalidSessionEventListenerClass(sessionEventListenerClassName)); } } catch (IllegalAccessException | InstantiationException | PrivilegedActionException 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){ try { Class exceptionHandlerClass = findClassForProperty(exceptionHandlerClassName,PersistenceUnitProperties.EXCEPTION_HANDLER_CLASS, loader); ExceptionHandler exceptionHandler = (ExceptionHandler)buildObjectForClass(exceptionHandlerClass, ExceptionHandler.class); if (exceptionHandler!=null){ session.setExceptionHandler(exceptionHandler); } else { session.handleException(ValidationException.invalidExceptionHandlerClass(exceptionHandlerClassName)); } } catch (IllegalAccessException | InstantiationException | PrivilegedActionException 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); switch (batchWritingSettingString) { case BatchWriting.JDBC -> { this.session.getPlatform().setUsesJDBCBatchWriting(true); this.session.getPlatform().setUsesNativeBatchWriting(false); } case BatchWriting.Buffered -> { this.session.getPlatform().setUsesJDBCBatchWriting(false); this.session.getPlatform().setUsesNativeBatchWriting(false); } case BatchWriting.OracleJDBC -> { this.session.getPlatform().setUsesNativeBatchWriting(true); this.session.getPlatform().setUsesJDBCBatchWriting(true); } case BatchWriting.None -> { // Nothing required. } default -> { if (batchWritingSettingString.equalsIgnoreCase("ExaLogic")) { batchWritingSettingString = "oracle.toplink.exalogic.batch.DynamicParameterizedBatchWritingMechanism"; } BatchWritingMechanism mechanism = null; try { Class cls = findClassForProperty(batchWritingSettingString, PersistenceUnitProperties.BATCH_WRITING, loader); Constructor constructor = cls.getConstructor(); mechanism = 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 { try { Class transportClass = findClassForProperty(repository, PersistenceUnitProperties.METADATA_SOURCE, loader); processor.setMetadataSource(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"; } try { Class tunerClass = findClassForProperty(tuning, PersistenceUnitProperties.TUNING, loader); tuner = 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 { try { Class transportClass = findClassForProperty(accessorType, PersistenceUnitProperties.PROJECT_CACHE, loader); projectCacheAccessor = 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"; } 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.isEmpty()) { 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.isEmpty())) { 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)); } } } /** * Enable or disable query result cache validation. * The method needs to be called in deploy stage. */ protected void updateAllowQueryResultsCacheValidation(Map m){ String allowQueryResultsCacheValidation = EntityManagerFactoryProvider.getConfigPropertyAsStringLogDebug(PersistenceUnitProperties.QUERY_RESULTS_CACHE_VALIDATION, m, session); if (allowQueryResultsCacheValidation != null) { if (allowQueryResultsCacheValidation.equalsIgnoreCase("true")) { session.getProject().setAllowQueryResultsCacheValidation(true); } else if (allowQueryResultsCacheValidation.equalsIgnoreCase("false")) { session.getProject().setAllowQueryResultsCacheValidation(false); } else { session.handleException(ValidationException.invalidBooleanValueForProperty(allowQueryResultsCacheValidation, PersistenceUnitProperties.QUERY_RESULTS_CACHE_VALIDATION)); } } } /** * 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: // Initialize with value in persitence.xml ValidationMode validationMode = persitenceUnitInfo.getValidationMode(); 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 compositeMemberPuInfos = getCompositeMemberPuInfoSet(persistenceUnitInfo, predeployProperties); // makes sure each member has a non-null property, overrides where required properties with composite's predeploy properties. updateCompositeMembersProperties(compositeMemberPuInfos, predeployProperties); // Don't log these properties - may contain passwords. The properties will be logged by contained persistence units. Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, predeployProperties); this.compositeMemberEmSetupImpls = new HashSet<>(compositeMemberPuInfos.size()); this.processor = new MetadataProcessor(); if (enableWeaving) { this.weaver = new PersistenceWeaver(new HashMap<>()); } // create containedEmSetupImpls and predeploy them for the first time. // predeploy divided in three stages (modes): // all composite members should complete a stage before any of them can move to the next one. for (SEPersistenceUnitInfo compositeMemberPuInfo : compositeMemberPuInfos) { // set composite's temporary classloader compositeMemberPuInfo.setNewTempClassLoader(tempClassLoader); String containedPuName = compositeMemberPuInfo.getPersistenceUnitName(); EntityManagerSetupImpl containedEmSetupImpl = new EntityManagerSetupImpl(containedPuName, containedPuName); // set composite containedEmSetupImpl.setCompositeEmSetupImpl(this); // non-null only in case predeploy is used for static weaving containedEmSetupImpl.setStaticWeaveInfo(this.staticWeaveInfo); // the properties guaranteed to be non-null after updateCompositeMemberProperties call Map compositeMemberProperties = (Map)compositeMemberMapOfProperties.get(containedPuName); containedEmSetupImpl.predeploy(compositeMemberPuInfo, compositeMemberProperties); // reset temporary classloader back to the original compositeMemberPuInfo.setNewTempClassLoader(compositeMemberPuInfo.getClassLoader()); this.compositeMemberEmSetupImpls.add(containedEmSetupImpl); } // after the first loop containedEmSetupImpls are in HalfPredeployed state, // mode = COMPOSITE_MEMBER_MIDDLE mode for(EntityManagerSetupImpl containedEmSetupImpl : this.compositeMemberEmSetupImpls) { // properties not used, puInfo already set containedEmSetupImpl.predeploy(null, null); } // after the second loop containedEmSetupImpls are still in HalfPredeployed state, // mode = COMPOSITE_MEMBER_FINAL mode for(EntityManagerSetupImpl containedEmSetupImpl : this.compositeMemberEmSetupImpls) { // properties not used, puInfo already set PersistenceWeaver containedWeaver = (PersistenceWeaver)containedEmSetupImpl.predeploy(null, null); // containedEmSetupImpl is finally in Predeployed state. // if both composite and composite member weavings enabled copy class details from member's weaver to composite's one. if(enableWeaving && containedWeaver != null) { this.weaver.getClassDetailsMap().putAll(containedWeaver.getClassDetailsMap()); } } if(enableWeaving && this.weaver.getClassDetailsMap().isEmpty()) { this.weaver = null; } } protected void deployCompositeMembers(Map deployProperties, ClassLoader realClassLoader) { // Don't log these properties - may contain passwords. The properties will be logged by contained persistence units. Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, deployProperties); for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) { // the properties guaranteed to be non-null after updateCompositeMemberProperties call Map compositeMemberProperties = (Map)compositeMemberMapOfProperties.get(compositeMemberEmSetupImpl.getPersistenceUnitInfo().getPersistenceUnitName()); compositeMemberEmSetupImpl.deploy(realClassLoader, compositeMemberProperties); AbstractSession containedSession = compositeMemberEmSetupImpl.getSession(); ((SessionBroker)session).registerSession(containedSession.getName(), containedSession); } } /** * INTERNAL: * Cause the first phase of metamodel initialization. This phase involves detecting the classes involved * and build metamodel instances for them. */ public void preInitializeMetamodel(){ // perform lazy initialisation Metamodel tempMetaModel = null; if (null == metaModel){ // 338837: verify that the collection is not empty - this would mean entities did not make it into the search path tempMetaModel = new MetamodelImpl(this); // set variable after init has executed without exception metaModel = tempMetaModel; } } /** * INTERNAL: * First phase of canonical metamodel initialization. For each class the metamodel is aware of, check * for a canonical metamodel class and initialize each attribute in it with a proxy that can cause the * rest of the metamodel population. Attributes are found reflectively rather than through the metamodel * to avoid having to further initialize the metamodel. */ public void preInitializeCanonicalMetamodel(EntityManagerFactoryImpl factory){ if (mustBeCompositeMember()) { // composite member // composite-unit can login and initialize (pre)initialize metamodel // if we are composite member, we cannot login, we have no session and no operations are allowed, // yet the factory can still be created as long as subsequent calls to createEntityManager fail with IllegalStateException AbstractSessionLog.getLog().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_not_preinit", getPersistenceUnitUniqueName()); return; } // 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 | IllegalAccessException pae){ getSession().logThrowable(SessionLog.FINEST, SessionLog.METAMODEL, pae); } catch (ConversionException ce){ } if (!classInitialized) { getSession().log(SessionLog.FINER, SessionLog.METAMODEL, "metamodel_canonical_model_class_not_found", className); } } } /* * Overide composite member properties' map with a new one, which * has (possibly empty but non-null) properties for each composite member, * for required properties overrides values with those from composite properties. */ protected void updateCompositeMembersProperties(Map compositeProperties) { Set compositePuInfos = new HashSet<>(compositeMemberEmSetupImpls.size()); for (EntityManagerSetupImpl compositeMemberEmSetupImpl : compositeMemberEmSetupImpls) { compositePuInfos.add((SEPersistenceUnitInfo)compositeMemberEmSetupImpl.persistenceUnitInfo); } updateCompositeMembersProperties(compositePuInfos, compositeProperties); } /* * Overide composite member properties' map with a new one, which * has (possibly empty but non-null) properties for each composite member, * for required properties overrides values with those from composite properties. * Parameter compositePuInfo indicates whether compositeMemberPreoperties should be merged (overriding) with its puInfo properties * (false for predeploy, true for deploy). */ protected void updateCompositeMembersProperties(Set compositePuInfos, Map compositeProperties) { // Don't log these properties - may contain passwords. The properties will be logged by contained persistence units. Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, compositeProperties); Map newCompositeMemberMapOfProperties; if (compositeMemberMapOfProperties == null) { newCompositeMemberMapOfProperties = new HashMap<>(compositePuInfos.size()); } else { // Don't alter user-supplied properties' map - create a copy instead newCompositeMemberMapOfProperties = new HashMap<>(compositeMemberMapOfProperties); } for (SEPersistenceUnitInfo compositePuInfo : compositePuInfos) { String compositeMemberPuName = compositePuInfo.getPersistenceUnitName(); Map compositeMemberProperties = (Map)newCompositeMemberMapOfProperties.get(compositeMemberPuName); Map newCompositeMemberProperties; if (compositeMemberProperties == null) { newCompositeMemberProperties = new HashMap<>(); } else { // Don't alter user-supplied properties - create a copy instead newCompositeMemberProperties = new HashMap<>(compositeMemberProperties); } overrideMemberProperties(newCompositeMemberProperties, compositeProperties); newCompositeMemberProperties = mergeMaps(newCompositeMemberProperties, compositePuInfo.getProperties()); translateOldProperties(newCompositeMemberProperties, session); newCompositeMemberMapOfProperties.put(compositeMemberPuName, newCompositeMemberProperties); } // set the new COMPOSITE_PROPERTIES into compositeProperties compositeProperties.put(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, newCompositeMemberMapOfProperties); } /* * For required properties overrides values with those from composite properties. */ protected static void overrideMemberProperties(Map memberProperties, Map compositeProperties) { String transactionTypeProp = (String)compositeProperties.get(PersistenceUnitProperties.TRANSACTION_TYPE); if (transactionTypeProp != null) { memberProperties.put(PersistenceUnitProperties.TRANSACTION_TYPE, transactionTypeProp); } else { memberProperties.remove(PersistenceUnitProperties.TRANSACTION_TYPE); } String serverPlatformProp = (String)compositeProperties.get(PersistenceUnitProperties.TARGET_SERVER); if (serverPlatformProp != null) { memberProperties.put(PersistenceUnitProperties.TARGET_SERVER, serverPlatformProp); } else { memberProperties.remove(PersistenceUnitProperties.TARGET_SERVER); } Boolean isValidationOnly = (Boolean)compositeProperties.get(PersistenceUnitProperties.VALIDATION_ONLY_PROPERTY); if (isValidationOnly != null) { memberProperties.put(PersistenceUnitProperties.VALIDATION_ONLY_PROPERTY, isValidationOnly); } else { memberProperties.remove(PersistenceUnitProperties.VALIDATION_ONLY_PROPERTY); } String archiveFactory = (String)compositeProperties.get(SystemProperties.ARCHIVE_FACTORY); if (archiveFactory != null) { memberProperties.put(SystemProperties.ARCHIVE_FACTORY, archiveFactory); } else { memberProperties.remove(SystemProperties.ARCHIVE_FACTORY); } } /* * If a member is composite then add its members instead. * All members' puNames must be unique. * Return a Map of composite member SEPersistenceUnitInfo keyed by persistence unit name. */ protected static Map getCompositeMemberPuInfoMap(PersistenceUnitInfo puInfo, Map predeployProperties) { Set memeberPuInfoSet = PersistenceUnitProcessor.getPersistenceUnits(puInfo.getClassLoader(), predeployProperties, puInfo.getJarFileUrls()); HashMap memberPuInfoMap = new HashMap<>(memeberPuInfoSet.size()); for (SEPersistenceUnitInfo memberPuInfo : memeberPuInfoSet) { // override transaction type with composite's transaction type memberPuInfo.setTransactionType(puInfo.getTransactionType()); // override properties that should be overridden by composit's properties overrideMemberProperties(memberPuInfo.getProperties(), puInfo.getProperties()); if (isComposite(memberPuInfo)) { Map containedMemberPuInfoMap = getCompositeMemberPuInfoMap(memberPuInfo, memberPuInfo.getProperties()); Iterator> it = containedMemberPuInfoMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry entry = it.next(); String containedMemberPuName = entry.getKey(); SEPersistenceUnitInfo containedMemberPuInfo = entry.getValue(); SEPersistenceUnitInfo anotherMemeberPuInfo = memberPuInfoMap.get(containedMemberPuName); if (anotherMemeberPuInfo == null) { memberPuInfoMap.put(containedMemberPuName, containedMemberPuInfo); } else { throwPersistenceUnitNameAlreadyInUseException(containedMemberPuName, containedMemberPuInfo, anotherMemeberPuInfo); } } } else { String memberPuName = memberPuInfo.getPersistenceUnitName(); SEPersistenceUnitInfo anotherMemeberPuInfo = memberPuInfoMap.get(memberPuName); if (anotherMemeberPuInfo == null) { memberPuInfoMap.put(memberPuName, memberPuInfo); } else { throwPersistenceUnitNameAlreadyInUseException(memberPuName, memberPuInfo, anotherMemeberPuInfo); } } } return memberPuInfoMap; } /* * If a member is composite then add its members instead. * All members' puNames must be unique. * Return a Set of composite member SEPersistenceUnitInfo. */ protected static Set getCompositeMemberPuInfoSet(PersistenceUnitInfo puInfo, Map predeployProperties) { return new HashSet<>(getCompositeMemberPuInfoMap(puInfo, predeployProperties).values()); } public static void throwPersistenceUnitNameAlreadyInUseException(String puName, PersistenceUnitInfo newPuInfo, PersistenceUnitInfo exsitingPuInfo) { String puUrl; String anotherPuUrl; puUrl = URLDecoder.decode(newPuInfo.getPersistenceUnitRootUrl().toString(), StandardCharsets.UTF_8); anotherPuUrl = URLDecoder.decode(exsitingPuInfo.getPersistenceUnitRootUrl().toString(), StandardCharsets.UTF_8); 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 refreshProperties = new HashMap<>(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(Map) */ @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); switch (databaseGenerationAction) { case SCHEMA_GENERATION_NONE_ACTION: break; case SCHEMA_GENERATION_CREATE_ACTION: writeDDL(SCHEMA_GENERATION_CREATE_SOURCE, SCHEMA_GENERATION_CREATE_SCRIPT_SOURCE, TableCreationType.CREATE, props, session, classLoader); break; case PersistenceUnitProperties.CREATE_OR_EXTEND: writeDDL(SCHEMA_GENERATION_CREATE_SOURCE, SCHEMA_GENERATION_CREATE_SCRIPT_SOURCE, TableCreationType.EXTEND, props, session, classLoader); break; case SCHEMA_GENERATION_DROP_ACTION: writeDDL(SCHEMA_GENERATION_DROP_SOURCE, SCHEMA_GENERATION_DROP_SCRIPT_SOURCE, TableCreationType.DROP, props, session, classLoader); break; case 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); break; case SCHEMA_GENERATION_VERIFY_ACTION: verifySchema(session, props); break; default: 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); switch (scriptsGenerationAction) { case SCHEMA_GENERATION_NONE_ACTION: break; case SCHEMA_GENERATION_CREATE_ACTION: writeMetadataDDLToScript(TableCreationType.CREATE, props, session, classLoader); break; case PersistenceUnitProperties.CREATE_OR_EXTEND: writeMetadataDDLToScript(TableCreationType.EXTEND, props, session, classLoader); break; case SCHEMA_GENERATION_DROP_ACTION: writeMetadataDDLToScript(TableCreationType.DROP, props, session, classLoader); break; case SCHEMA_GENERATION_DROP_AND_CREATE_ACTION: writeMetadataDDLToScript(TableCreationType.DROP_AND_CREATE, props, session, classLoader); break; default: 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 @SuppressWarnings("unchecked") Map compositeMemberMapOfProperties = (Map)getConfigProperty(PersistenceUnitProperties.COMPOSITE_UNIT_PROPERTIES, props); for(EntityManagerSetupImpl compositeMemberEmSetupImpl : this.compositeMemberEmSetupImpls) { // the properties guaranteed to be non-null after updateCompositeMemberProperties call @SuppressWarnings("unchecked") 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; switch (ddlGeneration) { case PersistenceUnitProperties.CREATE_ONLY: ddlType = TableCreationType.CREATE; break; case PersistenceUnitProperties.DROP_ONLY: ddlType = TableCreationType.DROP; break; case PersistenceUnitProperties.DROP_AND_CREATE: ddlType = TableCreationType.DROP_AND_CREATE; break; case PersistenceUnitProperties.CREATE_OR_EXTEND: ddlType = TableCreationType.EXTEND; break; default: // 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.emptyMap()); } /** * 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", new Object[]{SCHEMA_GENERATION_SCRIPTS_CREATE_TARGET})); } 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", new Object[]{SCHEMA_GENERATION_SCRIPTS_DROP_TARGET})); } 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); } /** * INTERNAL: * Verify database schema against the persistence unit metadata. * * @param session current database session * @param props persistence unit properties * @throws PersistenceException when validation fails. {@link SchemaValidationException} * with failures description is stored as a cause. */ private void verifySchema(DatabaseSessionImpl session, Map props) { SchemaManager schemaManager = new SchemaManager(session); ValidationFailure failures = new ValidationFailure(); String mode = getConfigPropertyAsString(PersistenceUnitProperties.SCHEMA_VALIDATION_MODE, props, PersistenceUnitProperties.SCHEMA_VALIDATION_MODE_SIMPLE) .toLowerCase(Locale.ROOT); boolean full = PersistenceUnitProperties.SCHEMA_VALIDATION_MODE_FULL.equals(mode); if (!schemaManager.validateDefaultTables(failures, true, full)) { throw new PersistenceException( ExceptionLocalization.buildMessage("schema_validation"), new SchemaValidationException( ExceptionLocalization.buildMessage("schema_validation_failed"), failures.result().toArray(new TableValidationException[0]))); } } /** * 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(), StandardCharsets.UTF_8); } else { throw new PersistenceException(ExceptionLocalization.buildMessage("jpa21-ddl-invalid-source-script-type", new Object[]{ source , source.getClass()})); } StringBuilder sqlBuffer; int data = reader.read(); // While there is still data to read, read line by line. while (data != -1) { sqlBuffer = new StringBuilder(); 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.isEmpty()) && (! 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"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy