persistence@glassfish.java.net

Re: Reminder: adding server platform and session name change into logger integration

From: Andrei Ilitchev <andrei.ilitchev_at_oracle.com>
Date: Sat, 4 Nov 2006 01:17:31 -0500

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