persistence@glassfish.java.net

Final review: adding server platform and session name change into logger integration

From: Marina Vatkina <Marina.Vatkina_at_Sun.COM>
Date: Mon, 06 Nov 2006 14:23:32 -0800

Andrei, Wonseok,

The (hopefully) final version is attached. Please let me know
if you have any other concerns.

thanks,
-marina

Andrei Ilitchev wrote On 11/03/06 22:17,:
> Marina,
> ----- Original Message -----
> From: "Marina Vatkina" <Marina.Vatkina_at_Sun.COM>
> To: <persistence_at_glassfish.dev.java.net>
> Sent: Friday, November 03, 2006 7:19 PM
> Subject: Re: Reminder: adding server platform and session name change into
> logger integration
>
>
>
>>Andrei, Wonseok,
>>
>>Today's version is attached.
>>
>>Andrei, it assumes your fix in NoServerPlatform, but still relies on the
>>return value from update... methods because otherwise the code will be
>>creating new instances of the loggers without real need for it (e.g. in
>>case
>>of a session name change when either loggerClass or serverPlatform has
>>changed
>>as well, or when comparing an existing logger class with the one provided
>>by
>>the platform). There was also a typo in your version, where you call
>>setServerSessionName instead of updateSessionName in updateServerSession.
>
> Alright.
> Just change in updateLoggers:
> if (loggerClassName != null &&
> !currentLog.getClass().getName().equals(loggerClassName)) {
> ...
> } else if(serverPlatformChanged) {
> ServerPlatform serverPlatform = session.getServerPlatform();
> singletonLog = serverPlatform.getServerLog();
> sessionLog = serverPlatform.getServerLog();
> }
> to:
> if (loggerClassName != null) {
> if(!currentLog.getClass().getName().equals(loggerClassName)) {
> ....
> }
> } else if(serverPlatformChanged) {
> ServerPlatform serverPlatform = session.getServerPlatform();
> singletonLog = serverPlatform.getServerLog();
> sessionLog = serverPlatform.getServerLog();
> }
>
> If loggerClassName is provided we shouldn't go to serverPlatform just
> because the provided class happens to be the same as the current one.
>
>
>>One more question for Tom and Andrei - predeployProperties is an instance
>>variable and it's some times used as-is and some times is passed around
>>as a parameter to other methods. Which one is correct?
>
> Both:
> some methods always use predeployProperies,
> others, like updateLoggers called several times with various maps.
>
>
>>As usual, I tested with in-container logging behavior, and e-t-p tests.
>>
>>thanks,
>>-marina
>>
>>Andrei Ilitchev wrote:
>>
>>>Marina, Wonseok,
>>>
>>>Attached is my version of EntityManagerSetupImpl class - I hope it's
>>>more simple.
>>>
>>>Also attached is a new version of NoServerPlatform class - the old one
>>>broke the pattern of creating a new instance of Log in getServer method.
>>>
>>>Thanks,
>>>
>>>Andrei
>>>
>>>----- Original Message ----- From: "Marina Vatkina"
>>><Marina.Vatkina_at_Sun.COM>
>>>To: <persistence_at_glassfish.dev.java.net>
>>>Sent: Friday, November 03, 2006 1:44 PM
>>>Subject: Reminder: adding server platform and session name change into
>>>logger integration
>>>
>>>
>>>
>>>>Tom, Andrei,
>>>>
>>>>Do you have any comments, or should I incorporate this last change
>>>>and check in the code? Will anybody want to see the final code, if
>>>>this is the only change?
>>>>
>>>>thanks,
>>>>-marina
>>>>
>>>>Marina Vatkina wrote:
>>>>
>>>>
>>>>>Hi Wonseok,
>>>>>
>>>>>Thanks for looking into this. Yeah, I was also thinking about it.
>>>>>It might even remove the need for the 'init' param - it's only
>>>>>used to bypass updateSessionName() call. So it'll be like
>>>>> updateLoggers(m, serverPlatformChanged, false);
>>>>>and
>>>>> updateLoggers(m, serverPlatformChanged, sessionNameChanged);
>>>>>
>>>>>I'll wait for Tom and Andrei to see if they have any other comments,
>>>>>before making further changes.
>>>>>
>>>>>thanks,
>>>>>-marina
>>>>>
>>>>>Wonseok Kim wrote:
>>>>>
>>>>>
>>>>>>Marina,
>>>>>>Thanks for solving the puzzle of the logger class change!
>>>>>>
>>>>>>It looks good except for one thing.
>>>>>>
>>>>>>Now updateServerPlatform() and updateSessionName() are done in
>>>>>>updateLoggers(), but doesn't it look a little bit awkward?
>>>>>>updateLoggers() just need to know whether ServerPlatform and session
>>>>>>name change. It would be easy to understand the code intuitively if
>>>>>>updateServerPlatform() and updateSessionName() are called in
>>>>>>predeploy() and updateServerSession() like below.
>>>>>>
>>>>>> protected void updateServerSession(Map m) {
>>>>>> ...
>>>>>> // In deploy Session name and ServerPlatform could've
>>>>>>changed which will affect the loggers.
>>>>>> boolean serverPlatformChanged = updateServerPlatform(m);
>>>>>> boolean sessionNameChanged = updateSessionName(m);
>>>>>> updateLoggers(m, false, serverPlatformChanged,
>>>>>>sessionNameChanged);
>>>>>>
>>>>>>Cheers,
>>>>>>-Wonseok
>>>>>>
>>>>>>On 11/3/06, * Marina Vatkina* <Marina.Vatkina_at_sun.com
>>>>>><mailto:Marina.Vatkina_at_sun.com>> wrote:
>>>>>>
>>>>>> Team,
>>>>>>
>>>>>> One more attempt to solve this puzzle is attached. Again, tested
>>>>>>in the
>>>>>> container and via e-p-t tests (i.e. no special testing for SE
>>>>>>changes of
>>>>>> the platform, session name, and logging).
>>>>>>
>>>>>> Please review *very carefully* ;).
>>>>>>
>>>>>> thanks,
>>>>>> -marina
>>>>>>
>>>>>> Marina Vatkina wrote:
>>>>>> > Hi Wonseok,
>>>>>> >
>>>>>> > Wonseok Kim wrote:
>>>>>> >
>>>>>> >> Hello Marina,
>>>>>> >>
>>>>>> >> I realized today that logger property(toplink.logging.logger
>>>>>>) can
>>>>>> >> change also in deploy phase like other properties.
>>>>>> >> If it is different, loggers should be updated also. Do you
>>>>>>want
>>>>>> to fix
>>>>>> >> it also or file it as another issue?
>>>>>> >
>>>>>> >
>>>>>> > Probably. Let me think about it.
>>>>>> >
>>>>>> >>
>>>>>> >> I found also that your modification is not using member
>>>>>>variable
>>>>>> >> "serverPlatform" anymore which you introduced before.
>>>>>> >
>>>>>> >
>>>>>> > Thanks.
>>>>>> >
>>>>>> >> As to session.setSessionLog(), just do as you wish, I think
>>>>>>it's
>>>>>> not a
>>>>>> >> big deal.
>>>>>> >
>>>>>> >
>>>>>> > OK.
>>>>>> >
>>>>>> > thanks,
>>>>>> > -marina
>>>>>> >
>>>>>> >>
>>>>>> >> Cheers,
>>>>>> >> -Wonseok
>>>>>> >>
>>>>>>
>>>>>>
>
>
> --------------------------------------------------------------------------------
>
>
>
>>/*
>>* 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<Class> buildEntityList(ClassLoader loader) {
>> ArrayList<Class> entityList = new ArrayList<Class>();
>> 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
>> * @param serverPlatformChanged the boolean that denotes a
>>serverPlatform change in the session.
>> * @param sessionNameChanged the boolean that denotes a
>>sessionNameChanged change in the session.
>> */
>> protected void updateLoggers(Map m, boolean serverPlatformChanged,
>>boolean sessionNameChanged) {
>> 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;
>> if (loggerClassName != null &&
>>!currentLog.getClass().getName().equals(loggerClassName)) {
>> // Logger class was specified and it's not what's already
>>there.
>> 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 if(serverPlatformChanged) {
>>// && !(serverPlatform instanceof NoServerPlatform)){
>> 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);
>> } else if (sessionNameChanged) {
>> // In JavaLog this will result in logger name changes,
>> // but won't affect DefaultSessionLog.
>> // Note, that the session hasn't change, only its name.
>> session.getSessionLog().setSession(session);
>> }
>>
>> //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 and ServerPlatform must be set prior to
>>setting the loggers.
>> setServerSessionName(predeployProperties);
>> updateServerPlatform(predeployProperties);
>>
>> // Update loggers and settings for the singleton logger and the
>>session logger.
>> updateLoggers(predeployProperties, true, false);
>>
>> 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;
>> }
>>
>> // In deploy Session name and ServerPlatform could've changed which
>>will affect the loggers.
>> boolean serverPlatformChanged = updateServerPlatform(m);
>> boolean sessionNameChanged = updateSessionName(m);
>>
>> updateLoggers(m, serverPlatformChanged, sessionNameChanged);
>>
>> 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);
>> 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;
>> }
>> }
>> }
>>}
>>


/*
 * 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<Class> buildEntityList(ClassLoader loader) {
        ArrayList<Class> entityList = new ArrayList<Class>();
        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
     * @param serverPlatformChanged the boolean that denotes a serverPlatform change in the session.
     * @param sessionNameChanged the boolean that denotes a sessionNameChanged change in the session.
     */
    protected void updateLoggers(Map m, boolean serverPlatformChanged, boolean sessionNameChanged) {
        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;
        if (loggerClassName != null) {
            if (!currentLog.getClass().getName().equals(loggerClassName)) {
                // Logger class was specified and it's not what's already there.
                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 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);
        } else if (sessionNameChanged) {
            // In JavaLog this will result in logger name changes,
            // but won't affect DefaultSessionLog.
            // Note, that the session hasn't change, only its name.
            session.getSessionLog().setSession(session);
        }

        //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 and ServerPlatform must be set prior to setting the loggers.
        setServerSessionName(predeployProperties);
        updateServerPlatform(predeployProperties);

        // Update loggers and settings for the singleton logger and the session logger.
        updateLoggers(predeployProperties, true, false);
        
        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;
        }

        // In deploy Session name and ServerPlatform could've changed which will affect the loggers.
        boolean serverPlatformChanged = updateServerPlatform(m);
        boolean sessionNameChanged = updateSessionName(m);

        updateLoggers(m, serverPlatformChanged, sessionNameChanged);

        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);
        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;
            }
        }
    }
}