/* * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the "License"). You may not use this file except * in compliance with the License. * * You can obtain a copy of the license at * glassfish/bootstrap/legal/CDDLv1.0.txt or * https://glassfish.dev.java.net/public/CDDLv1.0.html. * See the License for the specific language governing * permissions and limitations under the License. * * When distributing Covered Code, include this CDDL * HEADER in each file and include the License file at * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable, * add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your * own identifying information: Portions Copyright [yyyy] * [name of copyright owner] */ // Copyright (c) 1998, 2006, Oracle. All rights reserved. package oracle.toplink.essentials.internal.ejb.cmp3; import java.security.AccessController; import java.security.PrivilegedActionException; import java.util.*; import java.lang.reflect.Constructor; import javax.persistence.spi.PersistenceUnitInfo; import javax.persistence.spi.ClassTransformer; import javax.persistence.PersistenceException; import oracle.toplink.essentials.config.TopLinkProperties; import oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider; import oracle.toplink.essentials.internal.databaseaccess.DatasourcePlatform; import oracle.toplink.essentials.internal.ejb.cmp3.base.PropertiesHandler; import oracle.toplink.essentials.internal.weaving.TransformerFactory; import oracle.toplink.essentials.jndi.JNDIConnector; import oracle.toplink.essentials.logging.AbstractSessionLog; import oracle.toplink.essentials.logging.DefaultSessionLog; import oracle.toplink.essentials.logging.SessionLog; import oracle.toplink.essentials.internal.security.PrivilegedAccessHelper; import oracle.toplink.essentials.internal.security.PrivilegedClassForName; import oracle.toplink.essentials.internal.sessions.AbstractSession; import oracle.toplink.essentials.sequencing.Sequence; import oracle.toplink.essentials.sessions.*; import oracle.toplink.essentials.threetier.ReadConnectionPool; import oracle.toplink.essentials.threetier.ServerSession; import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataProcessor; import oracle.toplink.essentials.tools.sessionmanagement.SessionManager; import oracle.toplink.essentials.descriptors.ClassDescriptor; import oracle.toplink.essentials.internal.ejb.cmp3.base.CMP3Policy; import oracle.toplink.essentials.platform.server.CustomServerPlatform; import oracle.toplink.essentials.platform.server.ServerPlatform; import oracle.toplink.essentials.platform.server.NoServerPlatform; import oracle.toplink.essentials.exceptions.*; import oracle.toplink.essentials.internal.helper.EJB30ConversionManager; import javax.persistence.spi.PersistenceUnitTransactionType; import oracle.toplink.essentials.internal.ejb.cmp3.jdbc.base.DataSourceImpl; import oracle.toplink.essentials.tools.sessionconfiguration.DescriptorCustomizer; import oracle.toplink.essentials.tools.sessionconfiguration.SessionCustomizer; import oracle.toplink.essentials.internal.security.SecurableObjectHolder; import static oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider.*; /** * INTERNAL: * A TopLink specific implementer of the EntityManagerInitializer interface. */ public class EntityManagerSetupImpl { /* * 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. */ protected MetadataProcessor processor = null; protected PersistenceUnitInfo persistenceUnitInfo = null; protected Map predeployProperties = null; // may be positive only in STATE_DEPLOYED protected int deploymentCount = 0; protected ServerSession session = null; protected boolean isInContainerMode = false; // indicates whether weaving was used on the first run through predeploy (in STATE_INITIAL) protected boolean enableLazyForOneToOne = false; protected SecurableObjectHolder securableObjectHolder = new SecurableObjectHolder(); public static final String STATE_INITIAL = "Initial"; public static final String STATE_PREDEPLOYED = "Predeployed"; public static final String STATE_DEPLOYED = "Deployed"; public static final String STATE_UNDEPLOYED = "Undeployed"; protected String state = STATE_INITIAL; public static final String ERROR_LOADING_XML_FILE = "error_loading_xml_file"; public static final String EXCEPTION_LOADING_ENTITY_CLASS = "exception_loading_entity_class"; /** * This method can be used to ensure the session represented by emSetupImpl * is removed from the SessionManager. */ protected void removeSessionFromGlobalSessionManager() { if (session != null){ if(session.isConnected()) { session.logout(); } SessionManager.getManager().getSessions().remove(session.getName()); } } /** * Create a list of the entities that will be deployed. This list is build from the information * provided in the PersistenceUnitInfo argument. * The list contains Classes specified in the PersistenceUnitInfo's class list and also * files that are annotated with @Entity, @Embeddable and @MappedSuperclass in * the jar files provided in the persistence info. * This list of classes will used by TopLink to build a deployment project and to * decide what classes to weave. * @param loader * @return */ private Collection buildEntityList(ClassLoader loader) { ArrayList entityList = new ArrayList(); for (String className : processor.getProject().getEntityNames()) { try { Class entityClass = loader.loadClass(className); entityList.add(entityClass); } catch (ClassNotFoundException exc) { AbstractSessionLog.getLog().log(SessionLog.WARNING, "exception_loading_entity_class", className, exc); } } return entityList; } /** * 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 (provided the session is not connected) and * encrease deploymentCount (which decreased by calls to undeploy method). * * @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 predeployProperties 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 synchronized ServerSession deploy(ClassLoader realClassLoader, Map additionalProperties) { if(state != STATE_PREDEPLOYED && state != STATE_DEPLOYED) { throw new PersistenceException(EntityManagerSetupException.cannotDeployWithoutPredeploy(persistenceUnitInfo.getPersistenceUnitName())); } session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "deploy_begin", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), state, deploymentCount}); try { Map deployProperties = mergeMaps(additionalProperties, predeployProperties); translateOldProperties(deployProperties, session); if(state == STATE_PREDEPLOYED) { // The project is initially created using class names rather than classes. This call will make the conversion session.getProject().convertClassNamesToClasses(realClassLoader); // listeners and queries require the real classes and are therefore built during deploy using the realClassLoader processor.setClassLoader(realClassLoader); processor.addEntityListeners(); processor.addNamedQueries(); // free the resouces that we don't need any more. processor.cleanup(); processor = null; initServerSession(deployProperties); if (session.getIntegrityChecker().hasErrors()){ session.handleException(new IntegrityException(session.getIntegrityChecker())); } session.getDatasourcePlatform().getConversionManager().setLoader(realClassLoader); } deploymentCount++; state = STATE_DEPLOYED; try{ updateServerSession(deployProperties); if(!session.isConnected()) { if(isValidationOnly(deployProperties, false)) { session.initializeDescriptors(); } else { login(session, deployProperties); generateDDLFiles(session, deployProperties, !isInContainerMode); } } } catch (RuntimeException exception) { cleanUpSessionManager(); throw exception; } return session; } catch (oracle.toplink.essentials.exceptions.ValidationException exception) { throw new javax.persistence.PersistenceException(exception); } finally { session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "deploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), state, deploymentCount}); if(state == STATE_UNDEPLOYED) { session = null; } } } /** * INTERNAL: * Adds descriptors plus sequencing info found on the project to the session. */ protected void addProjectToSession(ServerSession session, Project project) { DatasourcePlatform sessionPlatform = (DatasourcePlatform)session.getDatasourceLogin().getDatasourcePlatform(); DatasourcePlatform projectPlatform = (DatasourcePlatform)project.getDatasourceLogin().getDatasourcePlatform(); if (!sessionPlatform.hasDefaultSequence() && projectPlatform.hasDefaultSequence()) { sessionPlatform.setDefaultSequence(projectPlatform.getDefaultSequence()); } if ((sessionPlatform.getSequences() == null) || sessionPlatform.getSequences().isEmpty()) { if ((projectPlatform.getSequences() != null) && !projectPlatform.getSequences().isEmpty()) { sessionPlatform.setSequences(projectPlatform.getSequences()); } } else { if ((projectPlatform.getSequences() != null) && !projectPlatform.getSequences().isEmpty()) { Iterator itProjectSequences = projectPlatform.getSequences().values().iterator(); while (itProjectSequences.hasNext()) { Sequence sequence = (Sequence)itProjectSequences.next(); if (!sessionPlatform.getSequences().containsKey(sequence.getName())) { sessionPlatform.addSequence(sequence); } } } } session.addDescriptors(project); } /** * INTERNAL: * Put the given session into the session manager so it can be looked up later */ protected void addSessionToGlobalSessionManager() { AbstractSession oldSession = (AbstractSession)SessionManager.getManager().getSessions().get(session.getName()); if(oldSession != null) { throw new PersistenceException(EntityManagerSetupException.attemptedRedeployWithoutClose(session.getName())); } SessionManager.getManager().addSession(session); } /** * INTERNAL: * Assign a CMP3Policy to each descriptor */ protected void assignCMP3Policy() { // all descriptors assigned CMP3Policy Project project = session.getProject(); for (Iterator iterator = project.getDescriptors().values().iterator(); iterator.hasNext();){ //bug:4406101 changed class cast to base class, which is used in projects generated from 904 xml ClassDescriptor descriptor = (ClassDescriptor)iterator.next(); if(descriptor.getCMPPolicy() == null) { descriptor.setCMPPolicy(new CMP3Policy()); } } } /** * INTERNAL: * Updates the TopLink ServerPlatform class for use with this platform. * @returns true if the ServerPlatform has changed. */ protected boolean updateServerPlatform(Map m) { String serverPlatformClassName = PropertiesHandler.getPropertyValueLogDebug(TopLinkProperties.TARGET_SERVER, m, session); if(serverPlatformClassName == null) { // property is not specified - nothing to do. return false; } // originalServerPlatform is always non-null - Session's constructor sets serverPlatform to NoServerPlatform ServerPlatform originalServerPlatform = session.getServerPlatform(); String originalServerPlatformClassName = originalServerPlatform.getClass().getName(); if(originalServerPlatformClassName.equals(serverPlatformClassName)) { // 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, TopLinkProperties.TARGET_SERVER); try { Constructor constructor = cls.getConstructor(new Class[]{oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.class}); serverPlatform = (ServerPlatform)constructor.newInstance(new Object[]{session}); } catch (Exception ex) { if(ExternalTransactionController.class.isAssignableFrom(cls)) { // the new serverPlatform is CustomServerPlatform, cls is its ExternalTransactionController class if(originalServerPlatform.getClass().equals(CustomServerPlatform.class)) { // both originalServerPlatform and the new serverPlatform are Custom, // just set externalTransactionController class (if necessary) into // originalServerPlatform CustomServerPlatform originalCustomServerPlatform = (CustomServerPlatform)originalServerPlatform; if(cls.equals(originalCustomServerPlatform.getExternalTransactionControllerClass())) { // externalTransactionController classes are the same - nothing to do } else { originalCustomServerPlatform.setExternalTransactionControllerClass(cls); } } else { // originalServerPlatform is not custom - need a new one. CustomServerPlatform customServerPlatform = new CustomServerPlatform(session); customServerPlatform.setExternalTransactionControllerClass(cls); serverPlatform = customServerPlatform; } } else { throw EntityManagerSetupException.failedToInstantiateServerPlatform(serverPlatformClassName, TopLinkProperties.TARGET_SERVER, ex); } } if (serverPlatform != null){ session.setServerPlatform(serverPlatform); return true; } return false; } /** * INTERNAL: * Update loggers and settings for the singleton logger and the session logger. * @param m the properties map */ protected void updateLoggers(Map m) { SessionLog currentLog = AbstractSessionLog.getLog(); // 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(TopLinkProperties.LOGGING_LOGGER, m, session); // The sessionLog instance should be different from the singletonLog because they have // different state. SessionLog singletonLog = null, sessionLog = null; ServerPlatform serverPlatform = session.getServerPlatform(); if (loggerClassName != null) { if(!currentLog.getClass().getName().equals(loggerClassName)) { // Logger class was specified and it's not what's already there. // If class not found then findClassProperty throws EntityManagerSetupException Class sessionLogClass = findClassForProperty(loggerClassName, TopLinkProperties.LOGGING_LOGGER); try { singletonLog = (SessionLog)sessionLogClass.newInstance(); sessionLog = (SessionLog)sessionLogClass.newInstance(); } catch (Exception ex) { throw EntityManagerSetupException.failedToInstantiateLogger(loggerClassName, TopLinkProperties.LOGGING_LOGGER, ex); } } } else { singletonLog = serverPlatform.getServerLog(); sessionLog = serverPlatform.getServerLog(); } if(currentLog.getClass() != singletonLog.getClass()) { AbstractSessionLog.setLog(singletonLog); session.setSessionLog(sessionLog); } //Bug5389828. Update the logging settings for the singleton logger. initOrUpdateLogging(m, AbstractSessionLog.getLog()); initOrUpdateLogging(m, session.getSessionLog()); } protected static Class findClass(String className) throws ClassNotFoundException, PrivilegedActionException { if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()){ return (Class)AccessController.doPrivileged(new PrivilegedClassForName(className)); } else { return oracle.toplink.essentials.internal.security.PrivilegedAccessHelper.getClassForName(className); } } protected static Class findClassForProperty(String className, String propertyName) { try { return findClass(className); } catch (PrivilegedActionException exception1) { throw EntityManagerSetupException.classNotFoundForProperty(className, propertyName, exception1.getException()); } catch (ClassNotFoundException exception2) { throw EntityManagerSetupException.classNotFoundForProperty(className, propertyName, exception2); } } protected void updateDescriptorCacheSettings(Map m) { Map typeMap = PropertiesHandler.getPrefixValuesLogDebug(TopLinkProperties.CACHE_TYPE_, m, session); Map sizeMap = PropertiesHandler.getPrefixValuesLogDebug(TopLinkProperties.CACHE_SIZE_, m, session); Map sharedMap = PropertiesHandler.getPrefixValuesLogDebug(TopLinkProperties.CACHE_SHARED_, m, session); if(typeMap.isEmpty() && sizeMap.isEmpty() && sharedMap.isEmpty()) { return; } boolean hasDefault = false; String defaultTypeName = (String)typeMap.remove(TopLinkProperties.DEFAULT); Class defaultType = null; if(defaultTypeName != null) { defaultType = findClassForProperty(defaultTypeName, TopLinkProperties.CACHE_TYPE_DEFAULT); hasDefault = true; } String defaultSizeString = (String)sizeMap.remove(TopLinkProperties.DEFAULT); Integer defaultSize = null; if(defaultSizeString != null) { defaultSize = Integer.parseInt(defaultSizeString); hasDefault = true; } String defaultSharedString = (String)sharedMap.remove(TopLinkProperties.DEFAULT); Boolean defaultShared = null; if(defaultSharedString != null) { defaultShared = Boolean.parseBoolean(defaultSharedString); hasDefault = true; } Iterator it = session.getDescriptors().values().iterator(); while (it.hasNext() && (hasDefault || !typeMap.isEmpty() || !sizeMap.isEmpty() || !sharedMap.isEmpty())) { ClassDescriptor descriptor = (ClassDescriptor)it.next(); if(descriptor.isAggregateDescriptor() || descriptor.isAggregateCollectionDescriptor()) { continue; } String entityName = descriptor.getAlias(); String className = descriptor.getJavaClass().getName(); String name; Class type = defaultType; name = entityName; String typeName = (String)typeMap.remove(name); if(typeName == null) { name = className; typeName = (String)typeMap.remove(name); } if(typeName != null) { type = findClassForProperty(typeName, TopLinkProperties.CACHE_TYPE_ + name); } if(type != null) { descriptor.setIdentityMapClass(type); } Integer size = defaultSize; name = entityName; String sizeString = (String)sizeMap.remove(name); if(sizeString == null) { name = className; sizeString = (String)sizeMap.remove(name); } if(sizeString != null) { size = Integer.parseInt(sizeString); } if(size != null) { descriptor.setIdentityMapSize(size.intValue()); } Boolean shared = defaultShared; name = entityName; String sharedString = (String)sharedMap.remove(name); if(sharedString == null) { name = className; sharedString = (String)sharedMap.remove(name); } if(sharedString != null) { shared = Boolean.parseBoolean(sharedString); } if(shared != null) { descriptor.setIsIsolated(!shared.booleanValue()); } } } /** * 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. * * @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 #predeploy(javax.persistence.spi.PersistenceUnitInfo, java.util.Map) */ public ClassTransformer predeploy(PersistenceUnitInfo info, Map extendedProperties) { if(state == STATE_INITIAL) { persistenceUnitInfo = info; } ClassLoader privateClassLoader = persistenceUnitInfo.getNewTempClassLoader(); predeployProperties = mergeMaps(extendedProperties, persistenceUnitInfo.getProperties()); // translate old properties // this should be done before using properties (i.e. ServerPlatform) translateOldProperties(predeployProperties, null); // create server session (it should be done before initializing ServerPlatform) session = new ServerSession(new Project(new DatabaseLogin())); // ServerSession name must be set prior to setting the loggers. setServerSessionName(predeployProperties); // ServerPlatform name must be set prior to setting the loggers. updateServerPlatform(predeployProperties); // Update loggers and settings for the singleton logger and the session logger. updateLoggers(predeployProperties); warnOldProperties(predeployProperties, session); session.getPlatform().setConversionManager(new EJB30ConversionManager()); if(!isValidationOnly(predeployProperties, false) && persistenceUnitInfo != null && persistenceUnitInfo.getTransactionType() == PersistenceUnitTransactionType.JTA) { if(persistenceUnitInfo.getJtaDataSource() == null) { throw new PersistenceException(EntityManagerSetupException.jtaPersistenceUnitInfoMissingJtaDataSource(persistenceUnitInfo.getPersistenceUnitName())); } } // this flag is used to disable work done as a result of the LAZY hint on OneToOne mappings if(state == STATE_INITIAL ) { enableLazyForOneToOne = true; String weaving = getConfigPropertyAsString(TopLinkProperties.WEAVING); if (weaving != null && weaving.equalsIgnoreCase("false")) { enableLazyForOneToOne = false; } } // Process the Object/relational metadata from XML and annotations. processORMetadata(privateClassLoader, session, enableLazyForOneToOne); // The connector will be reconstructed when the session is actually deployed session.getProject().getLogin().setConnector(new DefaultConnector()); 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 ClassTransformer transformer = null; if (enableLazyForOneToOne){ // build a list of entities the persistence unit represented by this EntityManagerSetupImpl will use Collection entities = buildEntityList(privateClassLoader); transformer = TransformerFactory.createTransformerAndModifyProject(session, entities, privateClassLoader); } state = STATE_PREDEPLOYED; return transformer; } /** * Check the provided map for an object with the given key. If that object is not available, check the * System properties. If it is not available from either location, return the default value. * @param propertyKey * @param defaultValue * @return */ public String getConfigPropertyAsString(String propertyKey, String defaultValue){ return getConfigPropertyAsStringLogDebug(propertyKey, predeployProperties, defaultValue, session); } public String getConfigPropertyAsString(String propertyKey){ return getConfigPropertyAsStringLogDebug(propertyKey, predeployProperties, session); } /** * 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. * @return */ 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(TOPLINK_VALIDATION_ONLY_PROPERTY, m, session); if(validationOnlyString != null) { return Boolean.parseBoolean(validationOnlyString); } else { return false; } } public boolean shouldGetSessionOnCreateFactory(Map m) { m = mergeWithExistingMap(m); return isValidationOnly(m, false); } protected Map mergeWithExistingMap(Map m) { if(predeployProperties != null) { return mergeMaps(m, predeployProperties); } else if(persistenceUnitInfo != null) { return mergeMaps(m, persistenceUnitInfo.getProperties()); } else { return m; } } public boolean isInContainerMode(){ return isInContainerMode; } /** * Override the default login creation method. * If persistenceInfo is available, use the information from it to setup the login * and possibly to set readConnectionPool. * @param m */ protected void updateLogins(Map m){ DatasourceLogin login = session.getLogin(); // 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(TopLinkProperties.JDBC_USER, m, session); String password = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_PASSWORD, m, session); if(user != null) { login.setUserName(user); } if(password != null) { login.setPassword(securableObjectHolder.getSecurableObject().decryptPassword(password)); } String toplinkPlatform = (String)PropertiesHandler.getPropertyValueLogDebug(TopLinkProperties.TARGET_DATABASE, m, session); if (toplinkPlatform != null) { login.setPlatformClassName(toplinkPlatform); } if (isValidationOnly(m, false) && persistenceUnitInfo.getTransactionType() == PersistenceUnitTransactionType.JTA && persistenceUnitInfo.getJtaDataSource() == null){ updateLoginDefaultConnector(login, m); return; } login.setUsesExternalTransactionController(persistenceUnitInfo.getTransactionType() == PersistenceUnitTransactionType.JTA); 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 = persistenceUnitInfo.getJtaDataSource(); // only define readDatasource if there is jta mainDatasource readDatasource = persistenceUnitInfo.getNonJtaDataSource(); } else { // JtaDataSource will be ignored because transactionType is RESOURCE_LOCAL if(persistenceUnitInfo.getJtaDataSource() != null) { session.log(SessionLog.WARNING, SessionLog.TRANSACTION, "resource_local_persistence_init_info_ignores_jta_data_source", persistenceUnitInfo.getPersistenceUnitName()); } if(persistenceUnitInfo.getNonJtaDataSource() != null) { mainDatasource = persistenceUnitInfo.getNonJtaDataSource(); } else { updateLoginDefaultConnector(login, m); return; } } // mainDatasource is guaranteed to be non null 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); login.setUsesExternalConnectionPooling(true); } // set readLogin if(readDatasource != null) { DatasourceLogin readLogin = (DatasourceLogin)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); session.setReadConnectionPool(readLogin); } } /** * 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. * @param login * @param m */ protected void updateLoginDefaultConnector(DatasourceLogin login, Map m){ 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(TopLinkProperties.JDBC_DRIVER, m, session); String connectionString = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_URL, m, session); if(connectionString != null) { dbLogin.setConnectionString(connectionString); } if(jdbcDriver != null) { dbLogin.setDriverClassName(jdbcDriver); } } } protected void updatePools(Map m) { // Sizes are irrelevant for external connection pool if(!session.getDefaultConnectionPool().getLogin().shouldUseExternalConnectionPooling()) { String strWriteMin = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_WRITE_CONNECTIONS_MIN, m, session); if(strWriteMin != null) { session.getDefaultConnectionPool().setMinNumberOfConnections(Integer.parseInt(strWriteMin)); } String strWriteMax = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_WRITE_CONNECTIONS_MAX, m, session); if(strWriteMax != null) { session.getDefaultConnectionPool().setMaxNumberOfConnections(Integer.parseInt(strWriteMax)); } } // Sizes and shared option are irrelevant for external connection pool if(!session.getReadConnectionPool().getLogin().shouldUseExternalConnectionPooling()) { String strReadMin = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_READ_CONNECTIONS_MIN, m, session); if(strReadMin != null) { session.getReadConnectionPool().setMinNumberOfConnections(Integer.parseInt(strReadMin)); } String strReadMax = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_READ_CONNECTIONS_MAX, m, session); if(strReadMax != null) { session.getReadConnectionPool().setMaxNumberOfConnections(Integer.parseInt(strReadMax)); } String strShouldUseShared = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_READ_CONNECTIONS_SHARED, m,session); if(strShouldUseShared != null) { boolean shouldUseShared = Boolean.parseBoolean(strShouldUseShared); boolean sessionUsesShared = session.getReadConnectionPool() instanceof ReadConnectionPool; if(shouldUseShared != sessionUsesShared) { Login readLogin = session.getReadConnectionPool().getLogin(); int nReadMin = session.getReadConnectionPool().getMinNumberOfConnections(); int nReadMax = session.getReadConnectionPool().getMaxNumberOfConnections(); if(shouldUseShared) { session.useReadConnectionPool(nReadMin, nReadMax); } else { session.useExclusiveReadConnectionPool(nReadMin, nReadMax); } // keep original readLogin session.getReadConnectionPool().setLogin(readLogin); } } } } /** * 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 TopLink defaults (for instance, in TopLink defaults binding to false, * EJB3 - to true). * This function applies defaults for such properties and registers the session. * All other session-related properties are applied in updateServerSession. * Note that updateServerSession may be called several times on the same session * (before login), but initServerSession is called just once - before the first call * to updateServerSession. * @param m */ protected void initServerSession(Map m) { assignCMP3Policy(); // Register session that has been created earlier. addSessionToGlobalSessionManager(); // shouldBindAllParameters is true by default - set it if no property provided if (EntityManagerFactoryProvider.getConfigPropertyAsString(TopLinkProperties.JDBC_BIND_PARAMETERS, m) == null) { // session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "property_value_default", new Object[]{TopLinkProperties.JDBC_BIND_PARAMETERS, "true"}); session.getPlatform().setShouldBindAllParameters(true); } // set default descriptor cache size - set it to all descriptors if CACHE_SIZE_DEFAULT not provided if (PropertiesHandler.getPrefixedPropertyValue(TopLinkProperties.CACHE_SIZE_, TopLinkProperties.DEFAULT, m) == null) { // int defaultCacheSize = Integer.parseInt(PropertiesHandler.getDefaultPropertyValueLogDebug(TopLinkProperties.CACHE_SIZE_, session)); int defaultCacheSize = Integer.parseInt(PropertiesHandler.getDefaultPropertyValue(TopLinkProperties.CACHE_SIZE_)); Iterator descriptorsIterator = session.getDescriptors().values().iterator(); while (descriptorsIterator.hasNext()) { ((ClassDescriptor)descriptorsIterator.next()).setIdentityMapSize(defaultCacheSize); } } } /** * Set ServerSession name but do not register the session. * The session registration should be done in sync * with increment of the deployment counter, as otherwise the * undeploy will not behave correctly in case of a more * than one predeploy request for the same session name. * @param m the combined properties map. */ protected void setServerSessionName(Map m) { // use default session name if none is provided String name = EntityManagerFactoryProvider.getConfigPropertyAsString(TopLinkProperties.SESSION_NAME, m); if(name == null) { if (persistenceUnitInfo.getPersistenceUnitRootUrl() != null){ name = persistenceUnitInfo.getPersistenceUnitRootUrl().toString() + "-" + persistenceUnitInfo.getPersistenceUnitName(); } else { name = persistenceUnitInfo.getPersistenceUnitName(); } } session.setName(name); } /** * Make any changes to our ServerSession that can be made after it is created. * @param m */ protected void updateServerSession(Map m) { if (session == null || session.isConnected()) { return; } // ServerSession name must be set prior to setting the loggers. setServerSessionName(m); // ServerPlatform name must be set prior to setting the loggers. updateServerPlatform(m); updateLoggers(m); String shouldBindString = getConfigPropertyAsStringLogDebug(TopLinkProperties.JDBC_BIND_PARAMETERS, m, session); if (shouldBindString != null) { session.getPlatform().setShouldBindAllParameters(Boolean.parseBoolean(shouldBindString)); } updateLogins(m); if(!session.getLogin().shouldUseExternalTransactionController()) { session.getServerPlatform().disableJTA(); } updatePools(m); updateDescriptorCacheSettings(m); // Customizers should be processed last processDescriptorCustomizers(m); processSessionCustomizer(m); } /** * This sets the isInContainerMode flag. * "true" indicates container case, "false" - SE. * @param isInContainerMode */ public void setIsInContainerMode(boolean isInContainerMode) { this.isInContainerMode = isInContainerMode; } protected void processSessionCustomizer(Map m) { String sessionCustomizerClassName = getConfigPropertyAsStringLogDebug(TopLinkProperties.SESSION_CUSTOMIZER, m, session); if(sessionCustomizerClassName == null) { return; } Class sessionCustomizerClass = findClassForProperty(sessionCustomizerClassName, TopLinkProperties.SESSION_CUSTOMIZER); SessionCustomizer sessionCustomizer; try { sessionCustomizer = (SessionCustomizer)sessionCustomizerClass.newInstance(); sessionCustomizer.customize(session); } catch (Exception ex) { throw EntityManagerSetupException.failedWhileProcessingProperty(TopLinkProperties.SESSION_CUSTOMIZER, sessionCustomizerClassName, ex); } } protected void initOrUpdateLogging(Map m, SessionLog log) { String logLevelString = PropertiesHandler.getPropertyValueLogDebug(TopLinkProperties.LOGGING_LEVEL, m, session); if(logLevelString != null) { log.setLevel(AbstractSessionLog.translateStringToLoggingLevel(logLevelString)); } String tsString = getConfigPropertyAsStringLogDebug(TopLinkProperties.LOGGING_TIMESTAMP, m, session); if (tsString != null) { log.setShouldPrintDate(Boolean.parseBoolean(tsString)); } String threadString = getConfigPropertyAsStringLogDebug(TopLinkProperties.LOGGING_THREAD, m, session); if (threadString != null) { log.setShouldPrintThread(Boolean.parseBoolean(threadString)); } String sessionString = getConfigPropertyAsStringLogDebug(TopLinkProperties.LOGGING_SESSION, m, session); if (sessionString != null) { log.setShouldPrintSession(Boolean.parseBoolean(sessionString)); } String exString = getConfigPropertyAsStringLogDebug(TopLinkProperties.LOGGING_EXCEPTIONS, m, session); if (exString != null) { log.setShouldLogExceptionStackTrace(Boolean.parseBoolean(exString)); } } /** * Updates server session name if changed. * @return true if the name has changed. */ protected boolean updateSessionName(Map m) { String newName = getConfigPropertyAsStringLogDebug(TopLinkProperties.SESSION_NAME, m, session); if(newName == null || newName.equals(session.getName())) { return false; } removeSessionFromGlobalSessionManager(); session.setName(newName); // In JavaLog this will result in logger name changes, // but won't affect DefaultSessionLog. session.getSessionLog().setSession(session); addSessionToGlobalSessionManager(); return true; } protected void processDescriptorCustomizers(Map m) { Map customizerMap = PropertiesHandler.getPrefixValuesLogDebug(TopLinkProperties.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(); ClassDescriptor descriptor = session.getDescriptorForAlias(name); if(descriptor == null) { try { Class javaClass = findClass(name); descriptor = session.getDescriptor(javaClass); } catch (Exception ex) { // Ignore exception } } if(descriptor != null) { String customizerClassName = (String)entry.getValue(); Class customizerClass = findClassForProperty(customizerClassName, TopLinkProperties.DESCRIPTOR_CUSTOMIZER_ + name); try { DescriptorCustomizer customizer = (DescriptorCustomizer)customizerClass.newInstance(); customizer.customize(descriptor); } catch (Exception ex) { throw EntityManagerSetupException.failedWhileProcessingProperty(TopLinkProperties.DESCRIPTOR_CUSTOMIZER_ + name, customizerClassName, ex); } } } } private void processORMetadata( ClassLoader privateClassLoader, AbstractSession session, boolean enableLazyForOneToOne){ processor = new MetadataProcessor(persistenceUnitInfo, session, privateClassLoader, enableLazyForOneToOne); // DO NOT CHANGE the order of invocation of various methods. // build the list of mapping files and read them. Need to do this before // we start processing entities as the list of entity classes // depend on metadata read from mapping files. boolean throwExceptionOnFail = "true".equalsIgnoreCase( getConfigPropertyAsString(TOPLINK_ORM_THROW_EXCEPTIONS, "true")); processor.readMappingFiles(throwExceptionOnFail); processor.buildEntityList(); // process persistence unit metadata/defaults defined in // ORM XML instance documents in the persistence unit processor.processPersistenceUnitMetadata(); processor.processMappingFiles(); processor.processAnnotations(); } public boolean isPredeployed() { return state == STATE_PREDEPLOYED; } public boolean isDeployed() { return state == STATE_DEPLOYED; } public boolean isUndeployed() { return state == STATE_UNDEPLOYED; } protected void cleanUpSessionManager() { deploymentCount--; if(deploymentCount > 0) { return; } state = STATE_UNDEPLOYED; removeSessionFromGlobalSessionManager(); } /** * Undeploy may be called several times, but only the call that decreases * deploymentCount to 0 disconnects the session and removes it from the session manager. * Note that the session is an attribute of this class, * and could be deployed again (after been undeployed to deploymentCount 0 and disconnected). */ public synchronized void undeploy() { if(state != STATE_DEPLOYED) { return; } session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "undeploy_begin", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), state, deploymentCount}); try { cleanUpSessionManager(); } finally { session.log(SessionLog.FINEST, SessionLog.PROPERTIES, "undeploy_end", new Object[]{getPersistenceUnitInfo().getPersistenceUnitName(), state, deploymentCount}); if(state == STATE_UNDEPLOYED) { session = null; } } } }