/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 1998, 2021 IBM Corporation. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
//     Mark Wolochuk - Bug 321041 ConcurrentModificationException on getFromIdentityMap() fix
//     11/07/2017 - Dalia Abo Sheasha
//       - 526957: Split the logging and trace messages
//     12/14/2017-3.0 Tomas Kraus
//       - 522635: ConcurrentModificationException when triggering lazy load from conforming query
package org.eclipse.persistence.internal.identitymaps;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.eclipse.persistence.config.ReferenceMode;
import org.eclipse.persistence.descriptors.CacheIndex;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy;
import org.eclipse.persistence.exceptions.DescriptorException;
import org.eclipse.persistence.exceptions.EclipseLinkException;
import org.eclipse.persistence.exceptions.QueryException;
import org.eclipse.persistence.exceptions.ValidationException;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.internal.descriptors.ObjectBuilder;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConcurrencyManager;
import org.eclipse.persistence.internal.helper.DeferredLockManager;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.InvalidObject;
import org.eclipse.persistence.internal.helper.WriteLockManager;
import org.eclipse.persistence.internal.localization.LoggingLocalization;
import org.eclipse.persistence.internal.localization.TraceLocalization;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetConstructorFor;
import org.eclipse.persistence.internal.security.PrivilegedInvokeConstructor;
import org.eclipse.persistence.internal.sessions.AbstractRecord;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.UnitOfWorkImpl;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.queries.InMemoryQueryIndirectionPolicy;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.Record;
import org.eclipse.persistence.sessions.SessionProfiler;
import org.eclipse.persistence.sessions.interceptors.CacheInterceptor;

/**
 * <p><b>Purpose</b>: Maintain identity maps for domain classes mapped with EclipseLink.
 * <p><b>Responsibilities</b>:<ul>
 *    <li> Build new identity maps lazily using info from the descriptor
 *    <li> Insert objects into appropriate identity map
 *    <li> Get object from appropriate identity map using object or primary key with class
 *    <li> Get and Set write lock values for cached objects
 * </ul>
 * @since TOPLink/Java 1.0
 */
public class IdentityMapManager implements Serializable, Cloneable {
    protected static final String MONITOR_PREFIX = SessionProfiler.CacheSize;

    /** A table of identity maps with the key being the domain Class. */
    protected Map<Class, IdentityMap> identityMaps;

    /** A table of identity maps with the key being the query */
    protected Map<Object, IdentityMap> queryResults;

    /** A map of class to list of queries that need to be invalidated when that class changes. */
    protected Map<Class, Set> queryResultsInvalidationsByClass;

    /** A map of indexes on the cache. */
    protected Map<CacheIndex, IdentityMap> cacheIndexes;

    /** A reference to the session owning this manager. */
    protected AbstractSession session;

    /** Ensure mutual exclusion depending on the cache isolation.*/
    protected transient ConcurrencyManager cacheMutex;

    /** PERF: Optimize the object retrieval from the identity map. */
    protected IdentityMap lastAccessedIdentityMap = null;

    /** Used to store the write lock manager used for merging. */
    protected transient WriteLockManager writeLockManager;

    /** PERF: Used to avoid readLock and profiler checks to improve performance. */
    protected boolean isCacheAccessPreCheckRequired;

    protected IdentityMapManager() {
    }

    public IdentityMapManager(AbstractSession session) {
        this.session = session;
        this.cacheMutex = new ConcurrencyManager();
        // PERF: Avoid query cache for uow as never used.
        if (session.isUnitOfWork()) {
            this.identityMaps = new HashMap();
        } else if (session.isIsolatedClientSession()) {
            this.identityMaps = new HashMap();
            this.queryResults = new HashMap();
            this.queryResultsInvalidationsByClass = new HashMap();
            this.cacheIndexes = new HashMap();
        } else {
            this.identityMaps = new ConcurrentHashMap();
            this.queryResults = new ConcurrentHashMap();
            this.queryResultsInvalidationsByClass = new ConcurrentHashMap();
            this.cacheIndexes = new ConcurrentHashMap();
        }
        checkIsCacheAccessPreCheckRequired();
    }

    /**
     * Provides access for setting a deferred lock on an object in the IdentityMap.
     */
    public CacheKey acquireDeferredLock(Object primaryKey, Class domainClass, ClassDescriptor descriptor, boolean isCacheCheckComplete) {
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireDeferredLock(primaryKey, isCacheCheckComplete);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && cacheKey.getObject() == null) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireDeferredLock(primaryKey, isCacheCheckComplete);
        }

        return cacheKey;
    }

    /**
     * Provides access for setting a concurrency lock on an object in the IdentityMap.
     * called with true from the merge process, if true then the refresh will not refresh the object.
     */
    public CacheKey acquireLock(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor, boolean isCacheCheckComplete) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquire();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireLock(primaryKey, forMerge, isCacheCheckComplete);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && (cacheKey != null) && cacheKey.getObject() == null) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireLock(primaryKey, forMerge, isCacheCheckComplete);
        }

        return cacheKey;
    }

    /**
     * Provides access for setting a concurrency lock on an object in the IdentityMap.
     * called with true from the merge process, if true then the refresh will not refresh the object.
     */
    public CacheKey acquireLockNoWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquire();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireLockNoWait(primaryKey, forMerge);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && (cacheKey != null) && (cacheKey.getObject() == null)) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireLockNoWait(primaryKey, forMerge);
        }

        return cacheKey;
    }

    /**
     * Provides access for setting a concurrency lock on an object in the IdentityMap.
     * called with true from the merge process, if true then the refresh will not refresh the object.
     */
    public CacheKey acquireLockWithWait(Object primaryKey, Class domainClass, boolean forMerge, ClassDescriptor descriptor, int wait) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquire();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            IdentityMap identityMap = getIdentityMap(descriptor, false);
            try {
                cacheKey = identityMap.acquireLockWithWait(primaryKey, forMerge, wait);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
            if (!this.session.isUnitOfWork() && (cacheKey != null) && cacheKey.getObject() == null) {
                this.session.updateProfile(MONITOR_PREFIX + domainClass.getSimpleName(), identityMap.getSize());
            }
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireLockWithWait(primaryKey, forMerge, wait);
        }

        return cacheKey;
    }

    /**
     * PERF: Used to micro optimize cache access.
     * Avoid the readLock and profile checks if not required.
     */
    public void checkIsCacheAccessPreCheckRequired() {
        if ((this.session.getProfiler() != null)
                || ((this.session.getDatasourceLogin() != null) && this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite())) {
            this.isCacheAccessPreCheckRequired = true;
        } else {
            this.isCacheAccessPreCheckRequired = false;
        }
    }

    /**
     * Provides access for setting a concurrency lock on an IdentityMap.
     */
    public void acquireReadLock() {
        this.session.startOperationProfile(SessionProfiler.Caching);

        if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite()) {
            getCacheMutex().acquireReadLock();
        }

        this.session.endOperationProfile(SessionProfiler.Caching);
    }

    /**
     * INTERNAL:
     * Find the cachekey for the provided primary key and place a readlock on it.
     * This will allow multiple users to read the same object but prevent writes to
     * the object while the read lock is held.
     */
    public CacheKey acquireReadLockOnCacheKey(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquireReadLock();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKey(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKey(primaryKey);
        }

        return cacheKey;
    }

    /**
     * INTERNAL:
     * Find the cachekey for the provided primary key and place a readlock on it.
     * This will allow multiple users to read the same object but prevent writes to
     * the object while the read lock is held.
     * If no readlock can be acquired then do not wait but return null.
     */
    public CacheKey acquireReadLockOnCacheKeyNoWait(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
        if (primaryKey == null) {
            CacheKey cacheKey = new CacheKey(null);
            cacheKey.acquireReadLock();
            return cacheKey;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKeyNoWait(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            cacheKey = getIdentityMap(descriptor, false).acquireReadLockOnCacheKeyNoWait(primaryKey);
        }

        return cacheKey;
    }

    /**
     * Lock the entire cache if the cache isolation requires.
     * By default concurrent reads and writes are allowed.
     * By write, unit of work merge is meant.
     */
    public boolean acquireWriteLock() {
        if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite() || this.session.getDatasourceLogin().shouldSynchronizeWrites()) {
            getCacheMutex().acquire();
            return true;
        }
        return false;
    }

    /**
     * INTERNAL: (Public to allow testing to access)
     * Return a new empty identity map to cache instances of the class.
     */
    public IdentityMap buildNewIdentityMap(ClassDescriptor descriptor) {
        if (this.session.isUnitOfWork()) {
            ReferenceMode mode = ((UnitOfWorkImpl)this.session).getReferenceMode();
            if (mode == ReferenceMode.FORCE_WEAK){
                return new WeakUnitOfWorkIdentityMap(32, descriptor, this.session, true);
            } else if (mode == ReferenceMode.WEAK && descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy()) {
                return new WeakUnitOfWorkIdentityMap(32, descriptor, this.session, true);
            } else {
                return new UnitOfWorkIdentityMap(32, descriptor, this.session, true);
            }
        }

        // Remote session has its own setting.
        if (this.session.isRemoteSession()) {
            return buildNewIdentityMap(descriptor.getRemoteIdentityMapClass(), descriptor.getRemoteIdentityMapSize(), descriptor, true);
        } else {
            return buildNewIdentityMap(descriptor.getIdentityMapClass(), descriptor.getIdentityMapSize(), descriptor, this.session.isIsolatedClientSession());
        }
    }

    /**
     * INTERNAL:
     * Return a new empty identity map of the class type.
     */
    protected <T extends IdentityMap> IdentityMap buildNewIdentityMap(Class<T> identityMapClass, int size, ClassDescriptor descriptor, boolean isIsolated) throws DescriptorException {
        if ((descriptor == null) || (descriptor.getCachePolicy().getCacheInterceptorClass() == null)) {
            // PERF: Avoid reflection.
            if (identityMapClass == ClassConstants.SoftCacheWeakIdentityMap_Class) {
                return new SoftCacheWeakIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.HardCacheWeakIdentityMap_Class) {
                return new HardCacheWeakIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.SoftIdentityMap_Class) {
                return new SoftIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.WeakIdentityMap_Class) {
                return new WeakIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.FullIdentityMap_Class) {
                return new FullIdentityMap(size, descriptor, this.session, isIsolated);
            } else if (identityMapClass == ClassConstants.CacheIdentityMap_Class) {
                return new CacheIdentityMap(size, descriptor, this.session, isIsolated);
            }
        }
        try {
            Class[] parameters = new Class[]{ClassConstants.PINT, ClassDescriptor.class, AbstractSession.class, boolean.class};
            Object[] values = new Object[]{size, descriptor, this.session, isIsolated};
            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                Constructor<T> constructor = AccessController.doPrivileged(new PrivilegedGetConstructorFor<>(identityMapClass, parameters, false));
                IdentityMap map = AccessController.doPrivileged(new PrivilegedInvokeConstructor<>(constructor, values));
                if ((descriptor != null) && (descriptor.getCachePolicy().getCacheInterceptorClass() != null)) {
                    Constructor<? extends CacheInterceptor> interceptor = AccessController.doPrivileged(new PrivilegedGetConstructorFor<>(descriptor.getCacheInterceptorClass(), new Class[] { IdentityMap.class, AbstractSession.class }, false));
                    Object params[] = new Object[]{map, this.session};
                    map = AccessController.doPrivileged(new PrivilegedInvokeConstructor<>(interceptor, params));
                }
                return map;
            } else {
                Constructor<T> constructor = PrivilegedAccessHelper.<T>getConstructorFor(identityMapClass, parameters, false);
                IdentityMap map = PrivilegedAccessHelper.<T>invokeConstructor(constructor, values);
                if ((descriptor != null) && (descriptor.getCacheInterceptorClass() != null)) {
                    Constructor<? extends CacheInterceptor> interceptor = PrivilegedAccessHelper.getConstructorFor(descriptor.getCacheInterceptorClass(), new Class[] { IdentityMap.class, AbstractSession.class }, false);
                    Object params[] = new Object[]{map, this.session};
                    map = PrivilegedAccessHelper.invokeConstructor(interceptor, params);
                }
                return map;
            }
        } catch (Exception exception) {
            throw DescriptorException.invalidIdentityMap(descriptor, exception);
        }
    }

    /**
     * INTERNAL:
     * Clear the the lastAccessedIdentityMap and the lastAccessedIdentityMapClass
     */
    public void clearLastAccessedIdentityMap() {
        this.lastAccessedIdentityMap = null;
    }

    /**
     * INTERNAL:
     * Clones itself, used for uow commit and resume on failure.
     */
    @Override
    public Object clone() {
        IdentityMapManager manager = null;
        try {
            manager = (IdentityMapManager)super.clone();
            manager.setIdentityMaps(new ConcurrentHashMap());
            for (Iterator<Map.Entry<Class, IdentityMap>> iterator = this.identityMaps.entrySet().iterator(); iterator.hasNext();) {
                Map.Entry entry = (Map.Entry)iterator.next();
                manager.identityMaps.put((Class)entry.getKey(), (IdentityMap)((IdentityMap)entry.getValue()).clone());
            }
        } catch (CloneNotSupportedException exception) {
            throw new InternalError(exception.toString());
        }
        return manager;
    }

    /**
     * Clear all the query caches.
     */
    public void clearQueryCache() {
        this.queryResults = new ConcurrentHashMap();
        this.queryResultsInvalidationsByClass = new ConcurrentHashMap();
    }

    /**
     * Clear all index caches.
     */
    public void clearCacheIndexes() {
        this.cacheIndexes = new ConcurrentHashMap();
    }

    /**
     * Remove the cache key related to a query.
     * Note this method is not synchronized and care should be taken to ensure
     * there are no other threads accessing the cache key.
     * This is used to clean up cached clones of queries.
     */
    public void clearQueryCache(ReadQuery query) {
        if (query != null) {// PERF: use query name, unless no name.
            Object queryKey = query.getName();
            if ((queryKey == null) || ((String)queryKey).length() == 0) {
                queryKey = query;
            }
            this.queryResults.remove(queryKey);
        }
    }

    /**
     * Invalidate/remove any results for the class from the query cache.
     * This is used to invalidate the query cache on any change.
     */
    public void invalidateQueryCache(Class classThatChanged) {
        if (this.queryResultsInvalidationsByClass == null) {
            return;
        }
        Set invalidations = this.queryResultsInvalidationsByClass.get(classThatChanged);
        if (invalidations != null) {
            for (Object queryKey : invalidations) {
                this.queryResults.remove(queryKey);
            }
        }
        Class superClass = classThatChanged.getSuperclass();
        if ((superClass != null) && (superClass != ClassConstants.OBJECT)) {
            invalidateQueryCache(superClass);
        }
    }

    /**
     * Return true if an CacheKey with the primary key is in the map.
     * User API.
     * @param key is the primary key for the object to search for.
     */
    public boolean containsKey(Object key, Class theClass, ClassDescriptor descriptor) {
        if (key == null) {
            return false;
        }
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return false;
        }
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                return map.containsKey(key);
            } finally {
                releaseReadLock();
                this.session.endOperationProfile(SessionProfiler.Caching);
            }
        } else {
            return map.containsKey(key);
        }
    }

    /**
     * Query the cache in-memory.
     */
    public Vector getAllFromIdentityMap(Expression selectionCriteria, Class theClass, Record translationRow, int valueHolderPolicy, boolean shouldReturnInvalidatedObjects) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        this.session.startOperationProfile(SessionProfiler.Caching);
        Vector objects = null;
        try {
            if (selectionCriteria != null) {
                // PERF: Avoid clone of expression.
                ExpressionBuilder builder = selectionCriteria.getBuilder();
                if (builder != null && builder.getSession() == null) {
                    builder.setSession(this.session.getRootSession(null));
                    builder.setQueryClass(theClass);
                }
            }
            objects = new Vector();
            IdentityMap map = getIdentityMap(descriptor, false);

            // Bug #522635 - if policy is set to trigger indirection, then iterate over a copy of the cache keys collection
            //               to avoid a ConcurrentModificationException
            final Enumeration<CacheKey> cacheEnum = valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION ? map.cloneKeys() : map.keys();

            // bug 327900 - If don't read subclasses is set on the descriptor heed it.
            boolean readSubclassesOrNoInheritance = (!descriptor.hasInheritance() || descriptor.getInheritancePolicy().shouldReadSubclasses());

            // cache the current time to avoid calculating it every time through the loop
            long currentTimeInMillis = System.currentTimeMillis();
            while (cacheEnum.hasMoreElements()) {
                CacheKey key = (CacheKey)cacheEnum.nextElement();
                if ((key.getObject() == null) || (!shouldReturnInvalidatedObjects && descriptor.getCacheInvalidationPolicy().isInvalidated(key, currentTimeInMillis))) {
                    continue;
                }
                Object object = key.getObject();

                // Bug # 3216337 - key.getObject() should check for null; object may be GC'd (MWN)
                if (object == null) {
                    continue;
                }

                // Must check for inheritance.
                // bug 327900
                if ((object.getClass() == theClass) || (readSubclassesOrNoInheritance && (theClass.isInstance(object)))) {
                    if (selectionCriteria == null) {
                        objects.add(object);
                    } else {
                        try {
                            if (selectionCriteria.doesConform(object, this.session, (AbstractRecord)translationRow, valueHolderPolicy)) {
                                objects.add(object);
                            }
                        } catch (QueryException queryException) {
                            if (queryException.getErrorCode() == QueryException.MUST_INSTANTIATE_VALUEHOLDERS) {
                                if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED) {
                                    objects.add(object);
                                } else if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_THROW_INDIRECTION_EXCEPTION) {
                                    throw queryException;
                                }
                            } else {
                                throw queryException;
                            }
                        }
                    }
                }
            }
        } finally {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }
        return objects;
    }

    /**
     * ADVANCED:
     * Using a list of Entity PK this method will attempt to bulk load the entire list from the cache.
     * In certain circumstances this can have large performance improvements over loading each item individually.
     * @param pkList List of Entity PKs to extract from the cache
     * @param descriptor Descriptor type to be retrieved.
     * @return Map of Entity PKs associated to the Entities that were retrieved
     */
    public Map<Object, Object> getAllFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor, AbstractSession session){
        return getIdentityMap(descriptor).getAllFromIdentityMapWithEntityPK(pkList, descriptor, session);
    }

    /**
     * ADVANCED:
     * Using a list of Entity PK this method will attempt to bulk load the entire list from the cache.
     * In certain circumstances this can have large performance improvements over loading each item individually.
     * @param pkList List of Entity PKs to extract from the cache
     * @param descriptor Descriptor type to be retrieved.
     * @return Map of Entity PKs associated to the Entities that were retrieved
     */
    public Map<Object, CacheKey> getAllCacheKeysFromIdentityMapWithEntityPK(Object[] pkList, ClassDescriptor descriptor, AbstractSession session){
        return getIdentityMap(descriptor).getAllCacheKeysFromIdentityMapWithEntityPK(pkList, descriptor, session);
    }

    /**
     * Invalidate objects meeting selectionCriteria.
     */
    public void invalidateObjects(Expression selectionCriteria, Class theClass, Record translationRow, boolean shouldInvalidateOnException) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        this.session.startOperationProfile(SessionProfiler.Caching);
        try {
            IdentityMap map = getIdentityMap(descriptor, true);
            if(map == null) {
                return;
            }
            boolean isChildDescriptor = descriptor.isChildDescriptor();
            if (selectionCriteria != null) {
                // PERF: Avoid clone of expression.
                ExpressionBuilder builder = selectionCriteria.getBuilder();
                if (builder.getSession() == null) {
                    builder.setSession(this.session.getRootSession(null));
                    builder.setQueryClass(theClass);
                }
                CacheInvalidationPolicy cacheInvalidationPolicy = descriptor.getCacheInvalidationPolicy();
                int inMemoryQueryIndirectionPolicy = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED;
                if (shouldInvalidateOnException) {
                    inMemoryQueryIndirectionPolicy = InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED;
                }

                // cache the current time to avoid calculating it every time through the loop
                long currentTimeInMillis = System.currentTimeMillis();
                //Enumeration doesn't checkReadLocks
                for (Enumeration<CacheKey> cacheEnum = map.keys(false); cacheEnum.hasMoreElements();) {
                    CacheKey key = (CacheKey)cacheEnum.nextElement();
                    Object object = key.getObject();
                    if (object == null || cacheInvalidationPolicy.isInvalidated(key, currentTimeInMillis)) {
                        continue;
                    }

                    // Must check for inheritance.
                    if (!isChildDescriptor || (object.getClass() == theClass) || (theClass.isInstance(object))) {
                        try {
                            if (selectionCriteria.doesConform(object, this.session, (AbstractRecord)translationRow, inMemoryQueryIndirectionPolicy)) {
                                key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                            }
                        } catch (QueryException queryException) {
                            if(queryException.getErrorCode() == QueryException.CANNOT_CONFORM_EXPRESSION) {
                                // if the expression can't be confirmed for the object it's likely the same will happen to all other objects -
                                // invalidate all objects of theClass if required, otherwise leave.
                                if (shouldInvalidateOnException) {
                                    invalidateObjects(null, theClass, null, true);
                                } else {
                                    return;
                                }
                            } else {
                                if (shouldInvalidateOnException) {
                                    key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                                }
                            }
                        } catch (RuntimeException runtimeException) {
                            if (shouldInvalidateOnException) {
                                key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                            }
                        }
                    }
                }
            } else {
                // selectionCriteria == null
                if(isChildDescriptor) {
                    // Must check for inheritance.
                    for (Enumeration<CacheKey> cacheEnum = map.keys(false); cacheEnum.hasMoreElements();) {
                        CacheKey key = (CacheKey)cacheEnum.nextElement();
                        Object object = key.getObject();
                        if (object == null) {
                            continue;
                        }

                        if ((object.getClass() == theClass) || (theClass.isInstance(object))) {
                            key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                        }
                    }
                } else {
                    // if it's either a root class or there is no inheritance just invalidate the whole identity map
                    for (Enumeration<CacheKey> cacheEnum = map.keys(false); cacheEnum.hasMoreElements();) {
                        CacheKey key = (CacheKey)cacheEnum.nextElement();
                        key.setInvalidationState(CacheKey.CACHE_KEY_INVALID);
                    }
                }
            }
            invalidateQueryCache(theClass);
        } finally {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }
    }

    /**
     * Retrieve the cache key for the given identity information.
     */
    public CacheKey getCacheKeyForObjectForLock(Object primaryKey, Class theClass, ClassDescriptor descriptor) {
        if (primaryKey == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKeyForLock(primaryKey);
            } finally {
                releaseReadLock();
                this.session.endOperationProfile(SessionProfiler.Caching);
            }
        } else {
            cacheKey = map.getCacheKeyForLock(primaryKey);
        }
        return cacheKey;
    }

    /**
     * Retrieve the cache key for the given identity information.
     */
    public CacheKey getCacheKeyForObject(Object primaryKey, Class theClass, ClassDescriptor descriptor, boolean forMerge) {
        if (primaryKey == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        CacheKey cacheKey = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKey(primaryKey, forMerge);
            } finally {
                releaseReadLock();
                this.session.endOperationProfile(SessionProfiler.Caching);
            }
        } else {
            cacheKey = map.getCacheKey(primaryKey, forMerge);
        }
        return cacheKey;
    }
    /**
     * Return the cache mutex.
     * This allows for the entire cache to be locked.
     * This is done for transaction isolations on merges, although never locked by default.
     */
    public ConcurrencyManager getCacheMutex() {
        return cacheMutex;
    }

    /**
     * This method is used to get a list of those classes with IdentityMaps in the Session.
     */
    public Vector getClassesRegistered() {
        Iterator<Class> classes = getIdentityMaps().keySet().iterator();
        Vector results = new Vector(getIdentityMaps().size());
        while (classes.hasNext()) {
            results.add(((Class)classes.next()).getName());
        }
        return results;
    }

    /**
     * Get the object from the identity map which has the same identity information
     * as the given object.
     */
    public Object getFromIdentityMap(Object object) {
        ClassDescriptor descriptor = this.session.getDescriptor(object);
        Object primaryKey = descriptor.getObjectBuilder().extractPrimaryKeyFromObject(object, this.session);
        return getFromIdentityMap(primaryKey, object.getClass(), descriptor);
    }

    /**
     * Get the object from the identity map which has the given primary key and class.
     */
    public Object getFromIdentityMap(Object key, Class theClass, ClassDescriptor descriptor) {
        return getFromIdentityMap(key, theClass, true, descriptor);
    }

    /**
     * Get the object from the identity map which has the given primary key and class.
     * Only return the object if it has not been invalidated.
     */
    public Object getFromIdentityMap(Object key, Class theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        if (key == null) {
            return null;
        }

        CacheKey cacheKey;
        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        Object domainObject = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKey(key, false);
            } finally {
                releaseReadLock();
            }
        } else {
            cacheKey = map.getCacheKey(key, false);
        }

        if ((cacheKey != null) && (shouldReturnInvalidatedObjects || !descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey))) {
            // BUG#4772232 - The read-lock must be checked to avoid returning a partial object,
            // PERF: Just check the read-lock to avoid acquire if not locked.
            // This is ok if you get the object first, as the object cannot gc and identity is always maintained.
            domainObject = cacheKey.getObject();
            cacheKey.checkReadLock();
            // Resolve the inheritance issues.
            domainObject = checkForInheritance(domainObject, theClass, descriptor);
        }

        if (this.isCacheAccessPreCheckRequired) {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }

        return domainObject;
    }

    public Object getFromIdentityMap(Expression selectionCriteria, Class theClass, Record translationRow, int valueHolderPolicy, boolean conforming, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        UnitOfWorkImpl unitOfWork = (conforming) ? (UnitOfWorkImpl)this.session : null;
        this.session.startOperationProfile(SessionProfiler.Caching);
        try {
            if (selectionCriteria != null) {
                // PERF: Avoid clone of expression.
                ExpressionBuilder builder = selectionCriteria.getBuilder();
                if (builder.getSession() == null) {
                    builder.setSession(this.session.getRootSession(null));
                    builder.setQueryClass(theClass);
                }
            }
            IdentityMap map = getIdentityMap(descriptor, false);

            // Bug #321041 - if policy is set to trigger indirection, then iterate over a copy of the cache keys collection
            //               to avoid a ConcurrentModificationException
            Enumeration<CacheKey> cacheEnum = valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_TRIGGER_INDIRECTION ? map.cloneKeys() : map.keys();

            // cache the current time to avoid calculating it every time through the loop
            long currentTimeInMillis = System.currentTimeMillis();
            while (cacheEnum.hasMoreElements()) {
                CacheKey key = (CacheKey)cacheEnum.nextElement();
                if (!shouldReturnInvalidatedObjects && descriptor.getCacheInvalidationPolicy().isInvalidated(key, currentTimeInMillis)) {
                    continue;
                }
                Object object = key.getObject();

                // Bug # 3216337 - key.getObject() should check for null; object may be GC'd (MWN)
                if (object == null) {
                    continue;
                }

                // Must check for inheritance.
                if ((object.getClass() == theClass) || (theClass.isInstance(object))) {
                    if (selectionCriteria == null) {
                        // bug 2782991: if first found was deleted nothing returned.
                        if (!(conforming && unitOfWork.isObjectDeleted(object))) {
                            return object;
                        }
                    }

                    //CR 3677 integration of a ValueHolderPolicy
                    try {
                        if (selectionCriteria.doesConform(object, this.session, (AbstractRecord)translationRow, valueHolderPolicy)) {
                            // bug 2782991: if first found was deleted nothing returned.
                            if (!(conforming && unitOfWork.isObjectDeleted(object))) {
                                return object;
                            }
                        }
                    } catch (QueryException queryException) {
                        if (queryException.getErrorCode() == QueryException.MUST_INSTANTIATE_VALUEHOLDERS) {
                            if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_CONFORMED) {
                                // bug 2782991: if first found was deleted nothing returned.
                                if (!(conforming && unitOfWork.isObjectDeleted(object))) {
                                    return object;
                                }
                            } else if (valueHolderPolicy == InMemoryQueryIndirectionPolicy.SHOULD_IGNORE_EXCEPTION_RETURN_NOT_CONFORMED) {
                                // For bug 2667870 just skip this item, but do not abort.
                            } else {
                                throw queryException;
                            }
                        } else {
                            throw queryException;
                        }
                    }
                }
            }
        } finally {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }
        return null;
    }

    /**
     * Get the object from the cache with the given primary key and class.
     * Do not return the object if it was invalidated.
     */
    public Object getFromIdentityMapWithDeferredLock(Object key, Class theClass, boolean shouldReturnInvalidatedObjects, ClassDescriptor descriptor) {
        if (key == null) {
            return null;
        }

        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return null;
        }
        CacheKey cacheKey;
        Object domainObject = null;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                cacheKey = map.getCacheKey(key, false);
            } finally {
                releaseReadLock();
            }
        } else {
            cacheKey = map.getCacheKey(key, false);
        }

        if ((cacheKey != null) && (shouldReturnInvalidatedObjects || !descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey))) {
            // PERF: Just check the read-lock to avoid acquire if not locked.
            // This is ok if you get the object first, as the object cannot gc and identity is always maintained.
            domainObject = cacheKey.getObject();
            cacheKey.checkDeferredLock();
            // Reslove inheritance issues.
            domainObject = checkForInheritance(domainObject, theClass, descriptor);
        }


        if (this.isCacheAccessPreCheckRequired) {
            this.session.endOperationProfile(SessionProfiler.Caching);
        }

        return domainObject;
    }

    /**
     * INTERNAL:
     * Return the identity map for the class, if missing create a new one.
     */
    public IdentityMap getIdentityMap(ClassDescriptor descriptor) {
        return  getIdentityMap(descriptor, false);
    }

    /**
     * INTERNAL:
     * Return the identity map for the class.
     * @param returnNullIfNoMap if true return null if no map, otherwise create one.
     */
    public IdentityMap getIdentityMap(ClassDescriptor descriptor, boolean returnNullIfNoMap) {
        // Ensure that an identitymap is only used for the root descriptor for inheritance.
        // This is required to obtain proper cache hits.
        if (descriptor.hasInheritance()) {
            descriptor = descriptor.getInheritancePolicy().getRootParentDescriptor();
        }
        Class descriptorClass = descriptor.getJavaClass();

        // PERF: First check if same as lastAccessedIdentityMap to avoid lookup.
        IdentityMap tempMap = this.lastAccessedIdentityMap;
        if ((tempMap != null) && (tempMap.getDescriptorClass() == descriptorClass)) {
            return tempMap;
        }

        // PERF: Avoid synchronization through get and putIfAbsent double-check.
        IdentityMap identityMap = this.identityMaps.get(descriptorClass);
        if (identityMap == null) {
            if (returnNullIfNoMap && descriptor.getCachePolicy().getCacheInterceptorClass() == null) {
                //interceptor monitors the identity map and needs to know that a request occurred.
                return null;
            }
            IdentityMap newIdentityMap = null;
            if (this.session.isUnitOfWork() || this.session.isIsolatedClientSession()) {
                newIdentityMap = buildNewIdentityMap(descriptor);
                identityMap = this.identityMaps.put(descriptorClass, newIdentityMap);
            } else {
                newIdentityMap = buildNewIdentityMap(descriptor);
                identityMap = (IdentityMap)((ConcurrentMap)this.identityMaps).putIfAbsent(descriptorClass, newIdentityMap);
            }
            if (identityMap == null) {
                identityMap = newIdentityMap;
            }
        }
        this.lastAccessedIdentityMap = identityMap;

        return identityMap;
    }

    protected Map<Class, IdentityMap> getIdentityMaps() {
        return identityMaps;
    }

    /**
     * Return an iterator of the classes in the identity map.
     */
    public Iterator getIdentityMapClasses() {
        return getIdentityMaps().keySet().iterator();
    }

    /**
     * Get the cached results associated with a query.  Results are cached by the
     * values of the parameters to the query so different parameters will have
     * different cached results.
     */
    public Object getQueryResult(ReadQuery query, List parameters, boolean shouldCheckExpiry) {
        if (query.getQueryResultsCachePolicy() == null) {
            return null;
        }
        // PERF: use query name, unless no name.
        Object queryKey = query.getName();
        if ((queryKey == null) || ((String)queryKey).length() == 0) {
            queryKey = query;
        }
        IdentityMap map = this.queryResults.get(queryKey);
        if (map == null) {
            return null;
        }

        Object lookupParameters;
        if ((parameters == null) || parameters.isEmpty()) {
            lookupParameters = CacheId.EMPTY;
        } else {
            lookupParameters = new CacheId(parameters.toArray());
        }

        CacheKey key = map.getCacheKey(lookupParameters, false);
        if ((key == null) || (shouldCheckExpiry && query.getQueryResultsCachePolicy().getCacheInvalidationPolicy().isInvalidated(key))) {
            return null;
        }
        return key.getObject();
    }

    /**
     * Return the cache key for the cache index or null if not found.
     */
    public CacheKey getCacheKeyByIndex(CacheIndex index, CacheId indexValues, boolean shouldCheckExpiry, ClassDescriptor descriptor) {
        if (this.cacheIndexes == null) {
            return null;
        }
        IdentityMap map = this.cacheIndexes.get(index);
        if (map == null) {
            return null;
        }

        CacheKey cacheKey = map.getCacheKey(indexValues, false);
        if (cacheKey == null) {
            return null;
        }
        // The cache key is nested as the object cache key is put into the cache.
        cacheKey = (CacheKey)cacheKey.getObject();
        if (cacheKey == null) {
            return null;
        }
        if (shouldCheckExpiry && descriptor.getCacheInvalidationPolicy().isInvalidated(cacheKey)) {
            return null;
        }
        return cacheKey;
    }

    /**
     * Index the cache key by the index values.
     */
    public void putCacheKeyByIndex(CacheIndex index, CacheId indexValues, CacheKey cacheKey, ClassDescriptor descriptor) {
        if (this.cacheIndexes == null) {
            return;
        }
        if (indexValues == null) {
            return;
        }
        IdentityMap map = this.cacheIndexes.get(index);
        if (map == null) {
            synchronized (this.cacheIndexes) {
                map = this.cacheIndexes.get(index);
                if (map == null) {
                    map = buildNewIdentityMap(index.getCacheType(), index.getCacheSize(), null, false);
                    this.cacheIndexes.put(index, map);
                }
            }
        }
        map.put(indexValues, cacheKey, null, 0);
    }

    protected AbstractSession getSession() {
        return session;
    }

    /**
     * Get the wrapper object from the cache key associated with the given primary key,
     * this is used for EJB.
     */
    public Object getWrapper(Object primaryKey, Class theClass) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        IdentityMap map = getIdentityMap(descriptor, false);
        Object wrapper;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                wrapper = map.getWrapper(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            wrapper = map.getWrapper(primaryKey);
        }
        return wrapper;
    }

    /**
     * Returns the single write Lock manager for this session
     */
    public WriteLockManager getWriteLockManager() {
        // With Isolated Sessions not all Identity maps need a WriteLockManager so
        //lazy initialize
        synchronized (this) {
            if (this.writeLockManager == null) {
                this.writeLockManager = new WriteLockManager();
            }
        }
        return this.writeLockManager;
    }

    /**
     * Retrieve the write lock value of the cache key associated with the given primary key,
     */
    public Object getWriteLockValue(Object primaryKey, Class domainClass, ClassDescriptor descriptor) {
        if (primaryKey == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, false);
        Object value;
        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            acquireReadLock();
            try {
                value = map.getWriteLockValue(primaryKey);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            value = map.getWriteLockValue(primaryKey);
        }
        return value;
    }

    /**
     * Reset the identity map for only the instances of the class.
     * For inheritance the user must make sure that they only use the root class.
     */
    public void initializeIdentityMap(Class theClass) throws EclipseLinkException {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);

        if (descriptor == null) {
            throw ValidationException.missingDescriptor(String.valueOf(theClass));
        }
        if (descriptor.isChildDescriptor()) {
            throw ValidationException.childDescriptorsDoNotHaveIdentityMap();
        }
        // Bug 3736313 - look up identity map by descriptor's java class
        Class javaClass = descriptor.getJavaClass();
        IdentityMap identityMap = buildNewIdentityMap(descriptor);
        getIdentityMaps().put(javaClass, identityMap);
        clearLastAccessedIdentityMap();
        invalidateQueryCache(theClass);
    }

    public void initializeIdentityMaps() {
        clearLastAccessedIdentityMap();
        setIdentityMaps(new ConcurrentHashMap());
        clearQueryCache();
        clearCacheIndexes();
    }

    /**
     * Used to print all the objects in the identity map of the passed in class.
     * The output of this method will be logged to this session's SessionLog at SEVERE level.
     */
    public void printIdentityMap(Class businessClass) {
        String cr = Helper.cr();
        ClassDescriptor descriptor = this.session.getDescriptor(businessClass);
        int cacheCounter = 0;
        StringWriter writer = new StringWriter();
        if (descriptor.isDescriptorTypeAggregate()) {
            return; //do nothing if descriptor is aggregate
        }

        IdentityMap map = getIdentityMap(descriptor, true);
        if (map == null) {
            return;
        }
        writer.write(LoggingLocalization.buildMessage("identitymap_for", new Object[] { cr, Helper.getShortClassName(map.getClass()), Helper.getShortClassName(businessClass) }));
        if (descriptor.hasInheritance()) {
            if (descriptor.getInheritancePolicy().isRootParentDescriptor()) {
                writer.write(LoggingLocalization.buildMessage("includes"));
                List<ClassDescriptor> childDescriptors = descriptor.getInheritancePolicy().getChildDescriptors();
                if ((childDescriptors != null) && (childDescriptors.size() != 0)) {//Bug#2675242
                    Iterator<ClassDescriptor> iterator = childDescriptors.iterator();
                    writer.write(Helper.getShortClassName(iterator.next().getJavaClass()));
                    while (iterator.hasNext()) {
                        writer.write(", " + Helper.getShortClassName(iterator.next().getJavaClass()));
                    }
                }
                writer.write(")");
            }
        }

        for (Enumeration<CacheKey> enumtr = map.keys(); enumtr.hasMoreElements();) {
            org.eclipse.persistence.internal.identitymaps.CacheKey cacheKey = (org.eclipse.persistence.internal.identitymaps.CacheKey)enumtr.nextElement();
            Object object = cacheKey.getObject();
            if (businessClass.isInstance(object)) {
                cacheCounter++;
                Object key = cacheKey.getKey();
                if (object == null) {
                    writer.write(LoggingLocalization.buildMessage("key_object_null", new Object[] { cr, key, "\t" }));
                } else {
                    String hashCode = String.valueOf(System.identityHashCode(object));
                    if (descriptor.usesOptimisticLocking() && descriptor.usesVersionLocking()) {
                        // Obtain writeLockValue and convert the value to String
                        Object writeLockValue = descriptor.getOptimisticLockingPolicy().getWriteLockValue(object, key, session);
                        String version = session.getPlatform().convertObject(writeLockValue, String.class);
                        writer.write(LoggingLocalization.buildMessage("key_version_identity_hash_code_object", new Object[] { cr, key, "\t", hashCode, object, version }));
                    } else {
                        writer.write(LoggingLocalization.buildMessage("key_identity_hash_code_object", new Object[] { cr, key, "\t", hashCode, object }));
                    }
                }
            }
        }
        writer.write(LoggingLocalization.buildMessage("elements", new Object[] { cr, String.valueOf(cacheCounter) }));
        this.session.log(SessionLog.SEVERE, SessionLog.CACHE, writer.toString(), null, null, false);
    }

    /**
     * Used to print all the objects in every identity map in this session.
     * The output of this method will be logged to this session's SessionLog at SEVERE level.
     */
    public void printIdentityMaps() {
        for (Iterator<Class<?>> iterator = this.session.getDescriptors().keySet().iterator();
             iterator.hasNext();) {
            Class businessClass = (Class)iterator.next();
            ClassDescriptor descriptor = this.session.getDescriptor(businessClass);
            if (descriptor.hasInheritance()) {
                if (descriptor.getInheritancePolicy().isRootParentDescriptor()) {
                    printIdentityMap(businessClass);
                }
            } else {
                printIdentityMap(businessClass);
            }
        }
    }

    /**
     * Used to print all the Locks in every identity map in this session.
     * The output of this method will be logged to this session's SessionLog at FINEST level.
     */
    public void printLocks() {
        StringWriter writer = new StringWriter();
        HashMap threadCollection = new HashMap();
        writer.write(TraceLocalization.buildMessage("lock_writer_header", null) + Helper.cr());
        Iterator<IdentityMap> idenityMapsIterator = this.session.getIdentityMapAccessorInstance().getIdentityMapManager().getIdentityMaps().values().iterator();
        while (idenityMapsIterator.hasNext()) {
            IdentityMap idenityMap = (IdentityMap)idenityMapsIterator.next();
            idenityMap.collectLocks(threadCollection);
        }
        Object[] parameters = new Object[1];
        for (Iterator threads = threadCollection.keySet().iterator(); threads.hasNext();) {
            Thread activeThread = (Thread)threads.next();
            parameters[0] = activeThread.getName();
            writer.write(TraceLocalization.buildMessage("active_thread", parameters) + Helper.cr());
            for (Iterator cacheKeys = ((HashSet)threadCollection.get(activeThread)).iterator();
                     cacheKeys.hasNext();) {
                CacheKey cacheKey = (CacheKey)cacheKeys.next();
                if (cacheKey.isAcquired() && cacheKey.getActiveThread() == activeThread){
                    parameters[0] = cacheKey.getObject();
                    writer.write(TraceLocalization.buildMessage("locked_object", parameters) + Helper.cr());
                    writer.write("PK: " + cacheKey.getKey() + Helper.cr());
                    parameters[0] = cacheKey.getDepth();
                    writer.write(TraceLocalization.buildMessage("depth", parameters) + Helper.cr());
                    Exception stack = cacheKey.getStack();
                    if (stack != null) stack.printStackTrace(new PrintWriter(writer));
                } else{
                    writer.write(TraceLocalization.buildMessage("cachekey_released", new Object[]{}));
                    parameters[0] = cacheKey.getObject();
                    writer.write(TraceLocalization.buildMessage("locked_object", parameters) + Helper.cr());
                    writer.write("PK: " + cacheKey.getKey() + Helper.cr());
                }
            }
            DeferredLockManager deferredLockManager = ConcurrencyManager.getDeferredLockManager(activeThread);
            if (deferredLockManager != null) {
                for (Iterator deferredLocks = deferredLockManager.getDeferredLocks().iterator();
                         deferredLocks.hasNext();) {
                    ConcurrencyManager lock = (ConcurrencyManager)deferredLocks.next();
                    if (lock instanceof CacheKey){
                        parameters[0] = ((CacheKey)lock).getObject();
                        writer.write(TraceLocalization.buildMessage("deferred_locks", parameters) + Helper.cr());
                    }
                }
            }
        }
        writer.write(Helper.cr() + TraceLocalization.buildMessage("lock_writer_footer", null) + Helper.cr());
        this.session.log(SessionLog.SEVERE, SessionLog.CACHE, writer.toString(), null, null, false);
    }

    /**
     * Used to print all the Locks in the specified identity map in this session.
     * The output of this method will be logged to this session's SessionLog at FINEST level.
     */
    public void printLocks(Class theClass) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        StringWriter writer = new StringWriter();
        HashMap threadCollection = new HashMap();
        writer.write(TraceLocalization.buildMessage("lock_writer_header", null) + Helper.cr());
        IdentityMap identityMap = getIdentityMap(descriptor, false);
        identityMap.collectLocks(threadCollection);

        Object[] parameters = new Object[1];
        for (Iterator threads = threadCollection.keySet().iterator(); threads.hasNext();) {
            Thread activeThread = (Thread)threads.next();
            parameters[0] = activeThread.getName();
            writer.write(TraceLocalization.buildMessage("active_thread", parameters) + Helper.cr());
            for (Iterator cacheKeys = ((HashSet)threadCollection.get(activeThread)).iterator();
                     cacheKeys.hasNext();) {
                CacheKey cacheKey = (CacheKey)cacheKeys.next();
                parameters[0] = cacheKey.getObject();
                writer.write(TraceLocalization.buildMessage("locked_object", parameters) + Helper.cr());
                parameters[0] = cacheKey.getDepth();
                writer.write(TraceLocalization.buildMessage("depth", parameters) + Helper.cr());
            }
            DeferredLockManager deferredLockManager = ConcurrencyManager.getDeferredLockManager(activeThread);
            if (deferredLockManager != null) {
                for (Iterator deferredLocks = deferredLockManager.getDeferredLocks().iterator();
                         deferredLocks.hasNext();) {
                    ConcurrencyManager lock = (ConcurrencyManager)deferredLocks.next();
                    if (lock instanceof CacheKey){
                        parameters[0] = ((CacheKey)lock).getObject();
                        writer.write(TraceLocalization.buildMessage("deferred_locks", parameters) + Helper.cr());
                    }
                }
            }
        }
        writer.write(Helper.cr() + TraceLocalization.buildMessage("lock_writer_footer", null) + Helper.cr());
        this.session.log(SessionLog.SEVERE, SessionLog.CACHE, writer.toString(), null, null, false);
    }

    /**
     * Register the object with the identity map.
     * The object must always be registered with its version number if optimistic locking is used.
     * The readTime may also be included in the cache key as it is constructed
     */
    public CacheKey putInIdentityMap(Object domainObject, Object keys, Object writeLockValue, long readTime, ClassDescriptor descriptor) {
        if (keys == null) {
            return null;
        }
        ObjectBuilder builder = descriptor.getObjectBuilder();
        Object implementation = builder.unwrapObject(domainObject, this.session);

        IdentityMap map = getIdentityMap(descriptor, false);
        CacheKey cacheKey;

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                cacheKey = map.put(keys, implementation, writeLockValue, readTime);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            cacheKey = map.put(keys, implementation, writeLockValue, readTime);
        }
        return cacheKey;
    }

    /**
     * Set the results for a query.
     * Query results are cached based on the parameter values provided to the query
     * different parameter values access different caches.
     */
    public void putQueryResult(ReadQuery query, List parameters, Object results) {
        if ((results == null) || (results == InvalidObject.instance())) {
            if (query.getQueryResultsCachePolicy().isNullIgnored()) {
                return;
            }
        }
        // PERF: use query name, unless no name.
        Object queryKey = query.getName();
        if ((queryKey == null) || ((String)queryKey).length() == 0) {
            queryKey = query;
        }
        IdentityMap map = this.queryResults.get(queryKey);
        if (map == null) {
            synchronized (this.queryResults) {
                map = this.queryResults.get(queryKey);
                if (map == null) {
                    int size = query.getQueryResultsCachePolicy().getMaximumCachedResults();
                    // PERF: If no parameters, then there can only be one result.
                    if ((parameters == null) || parameters.isEmpty()) {
                        size = 1;
                    }
                    map = buildNewIdentityMap(query.getQueryResultsCachePolicy().getCacheType(), size, null, false);
                    this.queryResults.put(queryKey, map);
                    // Mark the query to be invalidated for the query classes.
                    if (query.getQueryResultsCachePolicy().getInvalidateOnChange()) {
                        for (Class queryClass : query.getQueryResultsCachePolicy().getInvalidationClasses()) {
                            Set invalidations = this.queryResultsInvalidationsByClass.get(queryClass);
                            if (invalidations == null) {
                                invalidations = new HashSet();
                                this.queryResultsInvalidationsByClass.put(queryClass, invalidations);
                            }
                            invalidations.add(queryKey);
                        }
                    }
                }
            }
        }
        Object lookupParameters;
        if ((parameters == null) || parameters.isEmpty()) {
            lookupParameters = CacheId.EMPTY;
        } else {
            lookupParameters = new CacheId(parameters.toArray());
        }
        long queryTime = 0;
        if (query.isObjectLevelReadQuery()) {
            queryTime = ((ObjectLevelReadQuery)query).getExecutionTime();
        }
        if (queryTime == 0) {
            queryTime = System.currentTimeMillis();
        }
        // Bug 6138532 - store InvalidObject for "no results", do not store null
        if (results == null) {
            results = InvalidObject.instance();
        }
        map.put(lookupParameters, results, null, queryTime);
    }

    /**
     * Read-release the local-map and the entire cache.
     */
    protected void releaseReadLock() {
        if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite()) {
            getCacheMutex().releaseReadLock();
        }
    }

    /**
     * Lock the entire cache if the cache isolation requires.
     * By default concurrent reads and writes are allowed.
     * By write, unit of work merge is meant.
     */
    public void releaseWriteLock() {
       if (this.session.getDatasourceLogin().shouldSynchronizedReadOnWrite() || this.session.getDatasourceLogin().shouldSynchronizeWrites()) {
             getCacheMutex().release();
        }
    }

    /**
     * Remove the object from the object cache.
     */
    public Object removeFromIdentityMap(Object key, Class domainClass, ClassDescriptor descriptor, Object objectToRemove) {
        if (key == null) {
            return null;
        }
        IdentityMap map = getIdentityMap(descriptor, false);
        Object value;

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                value = map.remove(key, objectToRemove);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            value = map.remove(key, objectToRemove);
        }
        if (session.getProject().allowExtendedCacheLogging()) {
            session.log(SessionLog.FINEST, SessionLog.CACHE, "cache_item_removal", new Object[] {domainClass, key, Thread.currentThread().getId(), Thread.currentThread().getName()});
        }
        return value;
    }

    /**
     * Set the cache mutex.
     * This allows for the entire cache to be locked.
     * This is done for transaction isolations on merges, although never locked by default.
     */
    protected void setCacheMutex(ConcurrencyManager cacheMutex) {
        this.cacheMutex = cacheMutex;
    }

    public void setIdentityMaps(ConcurrentMap identityMaps) {
        clearLastAccessedIdentityMap();
        this.identityMaps = identityMaps;
    }

    protected void setSession(AbstractSession session) {
        this.session = session;
    }

    /**
     * Update the wrapper object the cache key associated with the given primary key,
     * this is used for EJB.
     */
    public void setWrapper(Object primaryKey, Class theClass, Object wrapper) {
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        IdentityMap map = getIdentityMap(descriptor, false);

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                map.setWrapper(primaryKey, wrapper);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            map.setWrapper(primaryKey, wrapper);
        }
    }

    /**
     * Update the write lock value of the cache key associated with the given primary key,
     */
    public void setWriteLockValue(Object primaryKey, Class theClass, Object writeLockValue) {
        if (primaryKey == null) {
            return;
        }
        ClassDescriptor descriptor = this.session.getDescriptor(theClass);
        IdentityMap map = getIdentityMap(descriptor, false);

        if (this.isCacheAccessPreCheckRequired) {
            this.session.startOperationProfile(SessionProfiler.Caching);
            // This is atomic so considered a read lock.
            acquireReadLock();
            try {
                map.setWriteLockValue(primaryKey, writeLockValue);
            } finally {
                releaseReadLock();
            }
            this.session.endOperationProfile(SessionProfiler.Caching);
        } else {
            map.setWriteLockValue(primaryKey, writeLockValue);
        }
    }

    /**
     * This method is used to resolve the inheritance issues arisen when conforming from the identity map
     * 1. Avoid reading the unintended subclass during in-memory query(e.g. when querying on large project, do not want
     *    to check small project,  both are inherited from the project, and stored in the same identity map).
     * 2. EJB container-generated classes broke the inheritance hierarchy. Need to use associated descriptor to track
     *    the relationship. CR4005-2612426, King-Sept-18-2002
     */
    protected Object checkForInheritance(Object domainObject, Class superClass, ClassDescriptor descriptor) {
        if ((domainObject != null) && ((domainObject.getClass() != superClass) && (!superClass.isInstance(domainObject)))) {
            // Before returning null, check if we are using EJB inheritance.
            if (descriptor.hasInheritance() && descriptor.getInheritancePolicy().getUseDescriptorsToValidateInheritedObjects()) {
                // EJB inheritance on the descriptors, not the container-generated classes/objects. We need to check the
                // identity map for the bean instance through the descriptor.
                if (descriptor.getInheritancePolicy().getSubclassDescriptor(domainObject.getClass()) == null) {
                    return null;
                }
                return domainObject;
            }
            return null;
        }
        return domainObject;
    }
}
