persistence@glassfish.java.net

Fix for issue 341

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Tue, 14 Mar 2006 14:38:48 -0800

Hi Tom,

Please review:

Index:
src/java/oracle/toplink/essentials/internal/ejb/cmp3/EntityManagerSetupImpl.java
===================================================================
RCS file:
/cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/ejb/cmp3/EntityManagerSetupImpl.java,v
retrieving revision 1.19
diff -r1.19 EntityManagerSetupImpl.java
473c473
< String throwXMLExceptions =
getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_ORM_THROW_EXCEPTIONS,
null);
---
 >         String throwXMLExceptions = 
getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_ORM_THROW_EXCEPTIONS, 
"true");
I also attached the changed file.
e-p-tests ran without regressions. I'll start QLook now.
thanks,
-marina


/*
 * 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.util.*;
import java.net.URL;
import java.lang.reflect.Constructor;
import java.io.IOException;

import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.ClassTransformer;
import javax.persistence.PersistenceException;

import oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider;
import oracle.toplink.essentials.internal.databaseaccess.DatasourcePlatform;
import oracle.toplink.essentials.internal.ejb.cmp3.metadata.MetadataDescriptor;
import oracle.toplink.essentials.internal.security.PrivilegedAccessController;
import oracle.toplink.essentials.internal.weaving.TransformerFactory;
import oracle.toplink.essentials.jndi.JNDIConnector;
import oracle.toplink.essentials.logging.AbstractSessionLog;
import oracle.toplink.essentials.logging.SessionLog;
import oracle.toplink.essentials.platform.database.oracle.OraclePlatform;
import oracle.toplink.essentials.platform.server.sunas.SunAS9ServerPlatform;
import oracle.toplink.essentials.internal.sessions.AbstractSession;
import oracle.toplink.essentials.sequencing.Sequence;
import oracle.toplink.essentials.sessions.*;
import oracle.toplink.essentials.threetier.ServerSession;
import oracle.toplink.essentials.internal.annotations.*;
import oracle.toplink.essentials.internal.ejb.cmp3.xml.EntityMappingsXMLProcessor;
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.NoServerPlatform;
import oracle.toplink.essentials.platform.server.ServerPlatform;
import oracle.toplink.essentials.exceptions.*;
import javax.persistence.spi.PersistenceUnitTransactionType;

/**
 * INTERNAL:
 * A TopLink specific implementer of the EntityManagerInitializer interface.
 */
public class EntityManagerSetupImpl {

    protected EJBAnnotationsProcessor processor = null;
    protected EntityMappingsXMLProcessor entityMappingsProcessor = null;
    protected PersistenceUnitInfo persistenceUnitInfo = null;
    protected Map extendedProperties = null;
    protected int logLevel;
    protected String deployedSessionName = null;
    protected Project sessionProject = null;
    private boolean validationOnly = false;

    //Bug#4452468 Used as an internal flag to indicate if there is no weaving (agent). By default, weaving is on.
        public static final String NO_WEAVING = "no.weaving";
        public static final String ERROR_LOADING_XML_FILE = "error_loading_xml_file";
        public static final String EXCEPTION_LOADING_ENTITY_CLASS = "exception_loading_entity_class";
        public static final int DEFAULT_DESCRIPTOR_CACHE_SIZE = 1000;
 
    /**
     * Build a default ServerSession. This will create an ServerSession with an empty login
     * that uses the OC4jServerPlatfrom
     */
    protected ServerSession buildDefaultSession(Project project) {
        ServerSession session = null;
        int maxConnections = ServerSession.MAX_WRITE_CONNECTIONS;
        int minConnections = ServerSession.MIN_WRITE_CONNECTIONS;
        
        String maxConnectionsString = getConfigPropertyAsString(EntityManagerFactoryProvider.MAX_WRITE_CONNECTIONS, "");
        if(!(maxConnectionsString.equals(""))) {
             maxConnections = Integer.parseInt(maxConnectionsString);
        }
        
        String minConnectionsString = getConfigPropertyAsString(EntityManagerFactoryProvider.MIN_WRITE_CONNECTIONS, "");
        if(!(minConnectionsString.equals(""))) {
            minConnections = Integer.parseInt(minConnectionsString);
        }
        
        //min and max connections should be set before login
        if (project == null) {
            Project newProject = new Project(new DatabaseLogin());
            session = new ServerSession(newProject, minConnections, maxConnections);
        } else {
            session = (ServerSession)project.createServerSession(minConnections, maxConnections);
        }
        
        String minReadConnectionsString = getConfigPropertyAsString(EntityManagerFactoryProvider.MIN_READ_CONNECTIONS, "");
        String maxReadConnectionsString = getConfigPropertyAsString(EntityManagerFactoryProvider.MAX_READ_CONNECTIONS, "");
        
        if( !(minReadConnectionsString.equals("")) & !(maxReadConnectionsString.equals(""))) {
            int minReadConnections = Integer.parseInt(minReadConnectionsString);
            int maxReadConnections = Integer.parseInt(maxReadConnectionsString);
            session.useExclusiveReadConnectionPool(minReadConnections, maxReadConnections);
        }
        
        if (logLevel >= 0) {
            session.getSessionLog().setLevel(logLevel);
        } else {
            session.getSessionLog().setLevel(SessionLog.INFO);
        }

        session.getLogin().usePlatform(new OraclePlatform());
        String bindAllParameters = getConfigPropertyAsString(EntityManagerFactoryProvider.BIND_ALL_PARAMETERS, "true");
        if (bindAllParameters.equalsIgnoreCase("false")) {
            session.getPlatform().setShouldBindAllParameters(false);
        } else {
            session.getPlatform().setShouldBindAllParameters(true);
        }
        if (persistenceUnitInfo != null && persistenceUnitInfo.getTransactionType() == PersistenceUnitTransactionType.JTA){
            session.setServerPlatform(new SunAS9ServerPlatform(session));
        }
        return session;
    }

    /**
     * INTERNAL:
     * Return a set of class names for each entity, embeddable, or mapped-superclass found
     * in the list of xml descriptor instance documents to be processed by the
     * EntityMappingsXMLProcessor.
     *
     * @param loader
     * @param persistenceUnitInfo
     * @return
     */
    public Set buildPersistentClassSet(ClassLoader loader, PersistenceUnitInfo persistenceUnitInfo) {
        HashSet classSet = new HashSet();
        if (persistenceUnitInfo != null) {
            if (!persistenceUnitInfo.getMappingFileNames().isEmpty()) {
                Iterator mappingFiles = persistenceUnitInfo.getMappingFileNames().iterator();
                String mappingFileResourceName = null;
                while (mappingFiles.hasNext()) {
                    try{
                        mappingFileResourceName = (String)mappingFiles.next();
                        URL mappingFileResource = loader.getResource(mappingFileResourceName);
                        classSet.addAll(EntityMappingsXMLProcessor.buildClassSet(mappingFileResource, loader));
                    } catch (RuntimeException e){
                        AbstractSessionLog.getLog().log(SessionLog.CONFIG, SessionLog.EJB_ORM, ERROR_LOADING_XML_FILE, new Object[] {mappingFileResourceName, e});
                    }
                }
            }
        }
        return classSet;
    }
    
    /**
     * Deploy a persistence session and return an EntityManagerFactory.
     *
     * @param entities The collection of persistent entity classes. These will have been
     * loaded by the loader that is also passed in. Any enhancement
     * and class manipulation must have already been done to the classes.
     * @param loader The class loader that was used to load the entity classes. This loader
     * will be maintained for the lifespan of the loaded classes.
     * @param datasourceName The name of the datasource that should be used for this
     * persistence session.
     * @return An EntityManagerFactory to be used by the Container to obtain EntityManagers
     */
    public ServerSession deploy(Collection entities, ClassLoader realClassLoader) {
        ServerSession session;
        session = buildDefaultSession(sessionProject);

        session.getProject().convertClassNamesToClasses(realClassLoader);
        
        if (persistenceUnitInfo.getPersistenceUnitRootUrl() != null){
            deployedSessionName = persistenceUnitInfo.getPersistenceUnitRootUrl().toString() + "-" + persistenceUnitInfo.getPersistenceUnitName();
        } else {
            deployedSessionName = persistenceUnitInfo.getPersistenceUnitName();
        }
        session.setName(deployedSessionName);

        addSessionToGlobalSessionManager(session);

        entityMappingsProcessor.setClassLoader(realClassLoader);
        entityMappingsProcessor.addEntityListeners(session);
        entityMappingsProcessor.addNamedQueriesToSession(session);

        // Set the real class loader on the processor before asking for
        // listeners and queries.
        processor.setClassLoader(realClassLoader);
        processor.addEntityListeners(session, entities);
        processor.addNamedQueriesToSession(session);
        
        String descriptorCacheSizeString = getConfigPropertyAsString(EntityManagerFactoryProvider.DESCRIPTOR_CACHE_SIZE, "");
        if(!(descriptorCacheSizeString.equals(""))) {
            int descriptorCacheSize = Integer.parseInt(descriptorCacheSizeString);
            Iterator descriptorsIterator = session.getProject().getOrderedDescriptors().iterator();
            while (descriptorsIterator.hasNext()) {
                 ((ClassDescriptor)descriptorsIterator.next()).setIdentityMapSize(descriptorCacheSize);
             }
        } else {
            Iterator descriptorsIterator = session.getProject().getOrderedDescriptors().iterator();
            while (descriptorsIterator.hasNext()) {
                 ((ClassDescriptor)descriptorsIterator.next()).setIdentityMapSize(DEFAULT_DESCRIPTOR_CACHE_SIZE);
             }
        }
        
        Map mergedProperties = EntityManagerFactoryProvider.mergePropertiesIntoMap(extendedProperties, persistenceUnitInfo.getProperties());
        //let the specific implementation decide when to login.
        ServerSession returnSession = updateServerSession(session, mergedProperties);
        cleanUp();

        if (returnSession.getIntegrityChecker().hasErrors()){
            returnSession.handleException(new IntegrityException(returnSession.getIntegrityChecker()));
        }

        returnSession.getDatasourcePlatform().getConversionManager().setLoader(realClassLoader);

        return returnSession;
    }


    /**
     * 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 static void addSessionToGlobalSessionManager(ServerSession ss) {
        AbstractSession session = (AbstractSession)SessionManager.getManager().getSessions().get(ss.getName());
        if(session != null) {
            throw new PersistenceException(EntityManagerSetupException.attemptedRedeployWithoutClose(ss.getName()));
        }
        SessionManager.getManager().addSession(ss);
    }

    /**
     * INTERNAL:
     * Assign a CMP3Policy to each descriptor
     */
    protected static void assignCMP3Policy(Project project) {
        // all descriptors assigned CMP3Policy
        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:
     * Build a default TopLink ServerPlatform class for use with this platform.
     */
    protected static void assignServerPlatform(ServerSession ss, Map m) {
        String serverPlatformClassName = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_SERVER_PLATFORM_PROPERTY, m, "");
        if(serverPlatformClassName.equals("")) {
            return;
        }

        ServerPlatform serverPlatform = null;
        try {
            Class cls = oracle.toplink.essentials.internal.security.PrivilegedAccessController.getClassForName(serverPlatformClassName);
            Constructor constructor = cls.getConstructor(new Class[]{oracle.toplink.essentials.internal.sessions.DatabaseSessionImpl.class});
            serverPlatform = (ServerPlatform)constructor.newInstance(new Object[]{ss});
        } catch (ClassNotFoundException ex1) {
            throw EntityManagerSetupException.classNotFoundForProperty(serverPlatformClassName, EntityManagerFactoryProvider.TOPLINK_SERVER_PLATFORM_PROPERTY, ex1);
        } catch (Exception ex2) {
            throw EntityManagerSetupException.failedToInstantiateServerPlatform(serverPlatformClassName, EntityManagerFactoryProvider.TOPLINK_SERVER_PLATFORM_PROPERTY, ex2);
        }
        
        if(serverPlatform instanceof CustomServerPlatform) {
            CustomServerPlatform customServerPlatform = (CustomServerPlatform)serverPlatform;
            String externalTransactionControllerClassName = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_EXTERNAL_TRANSACTION_CONTROLLER_PROPERTY, m, "");
            if(!externalTransactionControllerClassName.equals("")) {
                try{
                    customServerPlatform.setExternalTransactionControllerClass(oracle.toplink.essentials.internal.security.PrivilegedAccessController.getClassForName(externalTransactionControllerClassName));
                } catch (ClassNotFoundException ex1) {
                    throw EntityManagerSetupException.classNotFoundForProperty(externalTransactionControllerClassName, EntityManagerFactoryProvider.TOPLINK_EXTERNAL_TRANSACTION_CONTROLLER_PROPERTY, ex1);
                }
            }
        }
        ss.setServerPlatform(serverPlatform);

        //Initialize the log for the serverPlatform
        ss.setSessionLog(serverPlatform.getServerLog());

    }

    /**
     * Perform any steps necessary prior to actual deployment.
     *
     * @param sessionName The name of the persistence session. Null indicates that
     * the persistence layer should use its own default name.
     * @param entities The collection of persistent entity classes. These will have been
     * loaded by the loader that is also passed in.
     * @param privateClassLoader The class loader that was used to load the entity
     * classes. This loader (and all of the classes that it has
     * loaded) will disappear immediately after this call.
     * @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(Collection entities, ClassLoader privateClassLoader, PersistenceUnitInfo info)
     */
    public ClassTransformer predeploy(Collection entities, ClassLoader privateClassLoader, PersistenceUnitInfo info, Map extendedProperties) {
        persistenceUnitInfo = info;
        if(!validationOnly && persistenceUnitInfo != null && persistenceUnitInfo.getTransactionType() == PersistenceUnitTransactionType.JTA) {
            if(persistenceUnitInfo.getJtaDataSource() == null) {
                throw new PersistenceException(EntityManagerSetupException.jtaPersistenceUnitInfoMissingJtaDataSource(persistenceUnitInfo.getPersistenceUnitName()));
            }
        }
        this.extendedProperties = extendedProperties;

        logLevel = AbstractSessionLog.translateStringToLoggingLevel(getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_LOGGING_LEVEL, null));

        AbstractSession session = buildDefaultSession(null);
    
        boolean enableLazyForOneToOne = false;

        String noWeaving = getConfigPropertyAsString(NO_WEAVING, null);
        ClassTransformer transformer = null;
        if ((noWeaving == null) || noWeaving.equalsIgnoreCase("false")) {
            enableLazyForOneToOne = true;
        }

        entityMappingsProcessor = new EntityMappingsXMLProcessor(enableLazyForOneToOne);
        entityMappingsProcessor.setClassLoader(privateClassLoader);
        
        List<URL> mappingFileURLs = new Vector();
        List<String> mappingFileNames = new Vector();
        String ormStr = "META-INF/orm.xml";
        try{
            Enumeration<URL> resources = privateClassLoader.getResources(ormStr);
            while (resources.hasMoreElements()){
                mappingFileURLs.add(resources.nextElement());
                mappingFileNames.add(ormStr);
            }
            
        } catch (IOException e){/* ignore */}

        if (persistenceUnitInfo != null) {
            if (!persistenceUnitInfo.getMappingFileNames().isEmpty()) {
                mappingFileNames.addAll(persistenceUnitInfo.getMappingFileNames());
                Iterator mappingFiles = persistenceUnitInfo.getMappingFileNames().iterator();
                String mappingFileResourceName = null;
                while (mappingFiles.hasNext()) {
                    try{
                        mappingFileResourceName = (String)mappingFiles.next();
                        URL mappingFileResource = privateClassLoader.getResource(mappingFileResourceName);
                        mappingFileURLs.add(mappingFileResource);
                    } catch (RuntimeException e){
                        handleORMException(e, session, mappingFileResourceName);
                    }
                }
            }
        }
        
        // process persistence unit metadata/defaults defined in ORM XML instance documents in the persistence unit
        entityMappingsProcessor.processPersistenceUnitMetadata(session, mappingFileNames, entities);

        Iterator<URL> urls = mappingFileURLs.iterator();
        URL url = null;
        while (urls.hasNext()){
            try{
                url = urls.next();
                session = (AbstractSession)entityMappingsProcessor.processEntityMappings(session, url);
            } catch (RuntimeException e){
                handleORMException(e, session, url.toString());
            }
        }

        processor = new EJBAnnotationsProcessor(session, privateClassLoader, entities, enableLazyForOneToOne, entityMappingsProcessor.getDescriptorMetadataMap());
        session = processor.processORAnnotations();
        
        if (enableLazyForOneToOne){
            transformer = TransformerFactory.createTransformer(session, entities, privateClassLoader);
        }

        session.getProject().getLogin().setConnector(new DefaultConnector());
        sessionProject = session.getProject();

        if (session.getIntegrityChecker().hasErrors()){
            session.handleException(new IntegrityException(session.getIntegrityChecker()));
        }

        return transformer;
    }

    /**
     * Ensure any unnecessary data is nulled out to allow garbage collection
     */
    protected void cleanUp() {
        processor = null;
    }

    /**
     * INTERNAL:
     * Load a session from a given xml file. This method will first look for the session named by
     * sessionName, then for a session named: default and then for the only session in the xml.
     */
    public ServerSession getServerSession(Map m, ClassLoader classLoader) {
        // don't login the session
        ServerSession ss = (ServerSession)SessionManager.getManager().getSession(deployedSessionName, false);
        return updateServerSession(ss, m);
    }

      /**
   * 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 map
   * @param defaultValue
   * @return
   */
    public String getConfigPropertyAsString(String propertyKey, String defaultValue){
        String value = null;
        if (extendedProperties != null){
            value = (String)extendedProperties.get(propertyKey);
        }
        if (value == null){
            value = EntityManagerFactoryProvider.getConfigPropertyAsString(propertyKey, persistenceUnitInfo.getProperties(), defaultValue);
        }
        return value;
    }

    /**
     * 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 deployedSessionName;
    }
    
    /**
     * Handle an exception that occured while processing ORM xml
     */
    protected void handleORMException(RuntimeException e, AbstractSession session, String mappingFileResourceName){
        String throwXMLExceptions = getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_ORM_THROW_EXCEPTIONS, "true");
        // if fail quietly
        if (throwXMLExceptions == null || throwXMLExceptions.equalsIgnoreCase("false")) {
            session.log(SessionLog.CONFIG, SessionLog.EJB_ORM, ERROR_LOADING_XML_FILE, new Object[] {mappingFileResourceName, e});
        } else {
            // fail loudly
            session.handleException(e);
        }
    }
  /**
   * 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 ss
   * @param m
   */
    protected void updateLogin(ServerSession ss, Map m){
        DatasourceLogin login = ss.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 toplinkPlatform = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_PLATFORM_PROPERTY, m, "");
        if (!toplinkPlatform.equals("")) {
            login.setPlatformClassName(toplinkPlatform);
        }

        if (persistenceUnitInfo == null || (validationOnly && 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) {
                ss.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 = new JNDIConnector(mainDatasource);
            login.setConnector(jndiConnector);
            login.setUsesExternalConnectionPooling(true);
        }

        // set readLogin
        if(readDatasource != null) {
            DatasourceLogin readLogin = (DatasourceLogin)login.clone();
            readLogin.dontUseExternalTransactionController();
            JNDIConnector jndiConnector = new JNDIConnector(readDatasource);
            readLogin.setConnector(jndiConnector);
            ss.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 = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.JDBC_DRIVER_PROPERTY, m, "");
            String user = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.JDBC_USER_PROPERTY, m, "");
            String password = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.JDBC_PASSWORD_PROPERTY, m, "");
            String connectionString = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.JDBC_CONNECTION_STRING_PROPERTY, m, "");
            if(!user.equals("")) {
                dbLogin.setUserName(user);
            }
            if(!password.equals("")) {
                dbLogin.setPassword(password);
            }
            if(!connectionString.equals("")) {
                dbLogin.setConnectionString(connectionString);
            }
            if(!jdbcDriver.equals("")) {
                dbLogin.setDriverClassName(jdbcDriver);
            }
        }
    }

  /**
   * Make any changes to our ServerSession that can be made after it is created.
   * This includes setting the login information, platforms and CMP3Policy
   * @param ss
   * @param m
   * @return
   */
    protected ServerSession updateServerSession(ServerSession ss, Map m) {
        if (ss == null || ss.isConnected()) {
            return ss;
        }
        assignCMP3Policy(ss.getProject());

        updateLogin(ss, m);

        if(ss.getLogin().shouldUseExternalTransactionController()) {
            assignServerPlatform(ss, m);
        }
        String logLevel = EntityManagerFactoryProvider.getConfigPropertyAsString(EntityManagerFactoryProvider.TOPLINK_LOGGING_LEVEL, m, null);
        if (logLevel != null) {
            ss.getSessionLog().setLevel(AbstractSessionLog.translateStringToLoggingLevel(logLevel));
        }
        return ss;
    }

  /**
   * This sets the validate only flag. Validate only can be used to make an Entity
   * Manager check for deployment and errors.
   * @param validationOnly
   */
    public void setValidationOnly(boolean validationOnly) {
        this.validationOnly = validationOnly;
   }

}