/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. 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
//     @author  mobrien
//     @since   EclipseLink 1.0 enh# 235168
package org.eclipse.persistence.services;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.regex.PatternSyntaxException;

import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.internal.databaseaccess.DatabasePlatform;
import org.eclipse.persistence.internal.databaseaccess.DatasourcePlatform;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.identitymaps.CacheIdentityMap;
import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.FullIdentityMap;
import org.eclipse.persistence.internal.identitymaps.HardCacheWeakIdentityMap;
import org.eclipse.persistence.internal.identitymaps.IdentityMap;
import org.eclipse.persistence.internal.identitymaps.NoIdentityMap;
import org.eclipse.persistence.internal.identitymaps.SoftCacheWeakIdentityMap;
import org.eclipse.persistence.internal.identitymaps.SoftIdentityMap;
import org.eclipse.persistence.internal.identitymaps.WeakIdentityMap;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.DefaultSessionLog;
import org.eclipse.persistence.logging.JavaLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.platform.server.JMXEnabledPlatform;
import org.eclipse.persistence.sessions.DatabaseLogin;
import org.eclipse.persistence.sessions.DefaultConnector;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.ConnectionPool;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.tools.profiler.PerformanceProfiler;


/**
 * <p>
 * <b>Purpose</b>: Provide a dynamic interface into the EclipseLink Session.
 * <p>
 * <b>Description</b>: This class is meant to provide a framework for gaining access to configuration
 * of the EclipseLink Session during runtime.  It will provide the basis for development
 * of a JMX service and possibly other frameworks.
 *
 */
public abstract class RuntimeServices {

    /** stores access to the session object that we are controlling */
    protected Session session;

    /** This is the profile weight at server startup time. This is read-only */
    private int deployedSessionProfileWeight;

    /** This contains the session log from server startup time. This is read-only. */
    private SessionLog deployedSessionLog;

    public String objectName;

    protected static final String EclipseLink_Product_Name = "EclipseLink";
    /** Short name for the server platform - Must override in subclass */
    protected static String PLATFORM_NAME = "Server";

    /**
     *  Default Constructor
     */
    protected RuntimeServices() {
    }

    /**
     *  Constructor
     *  @param session the session to be used with these RuntimeServices
     */
    protected RuntimeServices(Session session) {
        this.session = session;
    }

    /**
     * INTERNAL:
     */
    protected AbstractSession getSession() {
        return (AbstractSession)this.session;
    }

    /**
     * Answer the name of the EclipseLink session this MBean represents.
     */
    public String getSessionName() {
        return getSession().getName();
    }

    /**
     * This method is used to determine if logging is turned on
     */
    public boolean getShouldLogMessages() {
        return getSession().shouldLogMessages();
    }

    /**
     *        This method is used to turn on Performance Profiling
     */
    public void setShouldProfilePerformance(boolean shouldProfile) {
        if (shouldProfile && (getSession().getProfiler() == null)) {
            getSession().setProfiler(new PerformanceProfiler());
        } else if (!shouldProfile) {
            getSession().setProfiler(null);
        }
    }

    /**
     *     This method will return if profiling is turned on or not
     */
    public boolean getShouldProfilePerformance() {
        return (getSession().getProfiler() != null) && ClassConstants.PerformanceProfiler_Class.isAssignableFrom(getSession().getProfiler().getClass());
    }

    /**
     *     This method is used to turn on Profile logging when using the Performance Profiler
     */
    public void setShouldLogPerformanceProfiler(boolean shouldLogPerformanceProfiler) {
        if ((getSession().getProfiler() != null) && ClassConstants.PerformanceProfiler_Class.isAssignableFrom(getSession().getProfiler().getClass())) {
            ((PerformanceProfiler)getSession().getProfiler()).setShouldLogProfile(shouldLogPerformanceProfiler);
        }
    }

    /**
     *     Method indicates if Performance profile should be logged
     */
    public boolean getShouldLogPerformanceProfiler() {
        if ((getSession().getProfiler() != null) && ClassConstants.PerformanceProfiler_Class.isAssignableFrom(getSession().getProfiler().getClass())) {
            return ((PerformanceProfiler)getSession().getProfiler()).shouldLogProfile();
        }
        return false;
    }

    /**
     *     Method used to set if statements should be cached.  Please note that Statements can not be cached when
     * using an external connection pool
     */
    public void setShouldCacheAllStatements(boolean shouldCacheAllStatements) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setShouldCacheAllStatements(shouldCacheAllStatements);
    }

    /**
     *     Used to set the statement cache size.  This is only valid if using cached Statements
     */
    public void setStatementCacheSize(int size) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatabaseLogin)getSession().getDatasourceLogin()).setStatementCacheSize(size);
    }

    /**
     *        Returns the statement cache size.  Only valid if statements are being cached
     */
    public int getStatementCacheSize() {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return 0;
        }
        return ((DatabaseLogin)getSession().getDatasourceLogin()).getStatementCacheSize();
    }

    /**
     * This method provide access for setting the sequence pre-allocation size
     */
    public void setSequencePreallocationSize(int size) {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return;
        }
        ((DatasourcePlatform)getSession().getDatasourcePlatform()).setSequencePreallocationSize(size);
    }

    /**
     *        Method returns the value of the Sequence Preallocation size
     */
    public int getSequencePreallocationSize() {
        if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
            return 0;
        }
        return ((DatasourcePlatform)getSession().getDatasourcePlatform()).getSequencePreallocationSize();
    }

    /**
     *     This method allows the client to set the pool size for a particular pool, based on the pool name
     * @param poolName the name of the pool to be updated.
     * @param maxSize the new maximum number of connections
     * @param minSize the new minimum number of connections
     */
    public void updatePoolSize(String poolName, int maxSize, int minSize) {
        if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
            ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
            if (connectionPool != null) {
                connectionPool.setMaxNumberOfConnections(maxSize);
                connectionPool.setMinNumberOfConnections(minSize);
            }
        }
    }

    /**
     *     This method will return the available Connection pools within this Server Session
     * @return java.util.List the available pools.
     */
    public List getAvailableConnectionPools() {
        Vector list = null;
        if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
            Map<String, ConnectionPool> pools = ((ServerSession)getSession()).getConnectionPools();
            list = new Vector(pools.size());
            Iterator<String> poolNames = pools.keySet().iterator();
            while (poolNames.hasNext()) {
                list.add(poolNames.next());
            }
        } else {
            list = new Vector();
        }
        return list;
    }

    /**
     *     This method will retrieve the size of a particular connection pool
     * @param poolName the name of the pool to get the size for
     * @return java.util.List a list containing two values. The first value is the Maximun size of the pool.
     * The second value is the Minimum size of the pool.
     */
    public List getSizeForPool(String poolName) {
        Vector results = new Vector(2);
        if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
            ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
            if (connectionPool != null) {
                results.add(connectionPool.getMaxNumberOfConnections());
                results.add(connectionPool.getMinNumberOfConnections());
            }
        }
        return results;
    }

    /**
     * This method provides client with access to add a new connection pool to a EclipseLink
     * ServerSession.
     * @param poolName the name of the new pool
     * @param maxSize the maximum number of connections in the pool
     * @param minSize the minimum number of connections in the pool
     * @param platform the fully qualified name of the EclipseLink platform to use with this pool.
     * @param driverClassName the fully qualified name of the JDBC driver class
     * @param url the URL of the database to connect to
     * @param userName the user name to connect to the database with
     * @param password the password to connect to the database with
     * @exception ClassNotFoundException if any of the class names are misspelled.
     */
    public void addNewConnectionPool(String poolName, int maxSize, int minSize, String platform, String driverClassName, String url, String userName, String password) throws ClassNotFoundException {
        if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
            DatabaseLogin login = new DatabaseLogin();
            login.setPlatformClassName(platform);
            login.setDriverClassName(driverClassName);
            login.setConnectionString(url);
            login.setUserName(userName);
            login.setEncryptedPassword(password);
            ((ServerSession)getSession()).addConnectionPool(poolName, login, minSize, maxSize);
        }
    }

    /**
     * This method is used to reset connections from the session to the database.  Please
     * Note that this will not work with a SessionBroker at this time
     */
    public void resetAllConnections() {
        if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
            Iterator<ConnectionPool> enumtr = ((ServerSession)getSession()).getConnectionPools().values().iterator();
            while (enumtr.hasNext()) {
                ConnectionPool pool = enumtr.next();
                pool.shutDown();
                pool.startUp();
            }
        } else if (ClassConstants.PublicInterfaceDatabaseSession_Class.isAssignableFrom(getSession().getClass())) {
            getSession().getAccessor().reestablishConnection(getSession());
        }
    }

    /**
     *        This method is used to return those Class Names that have identity Maps in the Session.
     * Please note that SubClasses and aggregates will be missing form this list as they do not have
     * separate identity maps.
     * @return java.util.List contains all of the classes which have identity maps in the current session.
     */
    public List getClassesInSession() {
        return getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
    }

    /**
     * This method will return a collection of the objects in the Identity Map.
     * There is no particular order to these objects.
     * @param className the fully qualified classname of the class to the instances of
     * @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
     */
    public List getObjectsInIdentityMap(String className) throws ClassNotFoundException {
        Class classToChange = getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange);

        Vector results = new Vector(map.getSize());
        Enumeration<CacheKey> objects = map.keys();
        while (objects.hasMoreElements()) {
            results.add(objects.nextElement().getObject());
        }
        return results;
    }

    /**
     *        This method is used to return the number of objects in a particular Identity Map
     * @param className the fully qualified name of the class to get number of instances of.
     * @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
     */
    public Integer getNumberOfObjectsInIdentityMap(String className) throws ClassNotFoundException {
        Class classToChange = getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        return getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange).getSize();
    }

    /**
     * This method is used to return a Map of the objects in a particular Identity Map's
     * subcache.  Only works for those identity Maps with a sub cache (ie Hard Cache Weak Identity Map)
     * This method replaces getObjectsInIdentityMapSubCache(className) which returns a list instead
     * of a Map
     * @param className the fully qualified name of the class to get number of instances of.
     * @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
     */
    public List getObjectsInIdentityMapSubCacheAsMap(String className) throws ClassNotFoundException {
        Class classToChange = getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange);

        //CR3855
        List subCache = new ArrayList(0);
        if (ClassConstants.HardCacheWeakIdentityMap_Class.isAssignableFrom(map.getClass())) {
            subCache = ((HardCacheWeakIdentityMap)map).getReferenceCache();
        }
        return subCache;
    }

    /**
     * This method is used to return the number of objects in a particular Identity Map's
     * subcache.  Only works for those identity Maps with a sub cache (ie Hard Cache Weak Identity Map)
     * @param className the fully qualified name of the class to get number of instances of.
     * @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
     */
    public Integer getNumberOfObjectsInIdentityMapSubCache(String className) throws ClassNotFoundException {
        //This needs to use the Session's active class loader (not implemented yet)
        Integer result = 0;
        Class classToChange = getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange);
        if (map.getClass().isAssignableFrom(ClassConstants.HardCacheWeakIdentityMap_Class)) {
            List subCache = ((HardCacheWeakIdentityMap)map).getReferenceCache();
            result = subCache.size();
        }
        return result;
    }

    /**
     * <p>
     * Return the log level
     * </p>
     * @param category  the string representation of an EclipseLink category, e.g. "sql", "transaction" ...
     * @return the log level
     */
    public int getLogLevel(String category) {
        return getSession().getLogLevel(category);
    }

    /**
     * <p>
     * Set the log level
     * </p>
     *
     * @param level     the new log level
     */
    public void setLogLevel(int level) {
        getSession().setLogLevel(level);
    }

    /**
     * <p>
     * Check if a message of the given level would actually be logged.
     * </p>
     *
     * @param Level  the log request level
     * @param category  the string representation of an EclipseLink category
     * @return true if the given message level will be logged
     */
    public boolean shouldLog(int Level, String category) {
        return getSession().shouldLog(Level, category);
    }

    /**
     * Return the DMS sensor weight
     */
    public int getProfileWeight() {
        if (getSession().isInProfile()) {
            return getSession().getProfiler().getProfileWeight();
        } else {
            return 0;
        }
    }

    /**
     *    This method is used to change DMS sensor weight.
     */
    public void setProfileWeight(int weight) {
        if (getSession().isInProfile()) {
            getSession().getProfiler().setProfileWeight(weight);
        }
    }

    /**
     *    This method is used to initialize the identity maps specified by className.
     * @param className the fully qualified classnames identifying the identity map to initialize
     */
     public synchronized void initializeIdentityMap(String className) throws ClassNotFoundException {
         Class registeredClass;

         //get identity map, and initialize
         registeredClass = getSession().getDatasourcePlatform().getConversionManager()
             .convertObject(className, ClassConstants.CLASS);
         getSession().getIdentityMapAccessor().initializeIdentityMap(registeredClass);
         ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_initialized", className);
     }

     /**
      *        This method will log the instance level locks in all Identity Maps in the session.
      */
      public void printIdentityMapLocks() {
          getSession().getIdentityMapAccessorInstance().getIdentityMapManager().printLocks();
      }

      /**
      *        This method will log the instance level locks in the Identity Map for the given class in the session.
      */
      public void printIdentityMapLocks(String registeredClassName) {
          Class registeredClass = getSession().getDatasourcePlatform().getConversionManager()
              .convertObject(registeredClassName, ClassConstants.CLASS);
          getSession().getIdentityMapAccessorInstance().getIdentityMapManager().printLocks(registeredClass);
      }

      /**
       *        This method assumes EclipseLink Profiling (as opposed to Java profiling).
       *        This will log at the INFO level a summary of all elements in the profile.
       */
       public void printProfileSummary() {
           if (!this.getUsesEclipseLinkProfiling()) {
               return;
           }
           PerformanceProfiler performanceProfiler = (PerformanceProfiler)getSession().getProfiler();
           getSession().getSessionLog().info(performanceProfiler.buildProfileSummary().toString());
       }

       /**
        * INTERNAL:
        * utility method to get rid of leading and trailing {}'s
        */
       private String trimProfileString(String originalProfileString) {
           String trimmedString;

           if (originalProfileString.length() > 1) {
               trimmedString = originalProfileString.substring(0, originalProfileString.length());
               if ((trimmedString.charAt(0) == '{') && (trimmedString.charAt(trimmedString.length() - 1) == '}')) {
                   trimmedString = trimmedString.substring(1, trimmedString.length() - 1);
               }
               return trimmedString;
           } else {
               return originalProfileString;
           }
       }

       /**
       *        This method assumes EclipseLink Profiling (as opposed to Java profiling).
       *        This will log at the INFO level a summary of all elements in the profile, categorized
       *        by Class.
       */
       public void printProfileSummaryByClass() {
           if (!this.getUsesEclipseLinkProfiling()) {
               return;
           }
           PerformanceProfiler performanceProfiler = (PerformanceProfiler)getSession().getProfiler();
           //trim the { and } from the beginning at end, because they cause problems for the logger
           getSession().getSessionLog().info(trimProfileString(performanceProfiler.buildProfileSummaryByClass().toString()));
       }

       /**
       *        This method assumes EclipseLink Profiling (as opposed to Java profiling).
       *        This will log at the INFO level a summary of all elements in the profile, categorized
       *        by Query.
       */
       public void printProfileSummaryByQuery() {
           if (!this.getUsesEclipseLinkProfiling()) {
               return;
           }
           PerformanceProfiler performanceProfiler = (PerformanceProfiler)getSession().getProfiler();
           getSession().getSessionLog().info(trimProfileString(performanceProfiler.buildProfileSummaryByQuery().toString()));
       }

       /**
        *        This method is used to get the type of profiling.
        *   Possible values are: "EclipseLink" or "None".
        */
        public synchronized String getProfilingType() {
            if (getUsesEclipseLinkProfiling()) {
                return EclipseLink_Product_Name;
            } else {
                return "None";
            }
        }

        /**
        *        This method is used to select the type of profiling.
        *   Valid values are: "EclipseLink" or "None". These values are not case sensitive.
        *   null is considered  to be "None".
        */
        public synchronized void setProfilingType(String profileType) {
            if ((profileType == null) || (profileType.compareToIgnoreCase("None") == 0)) {
                this.setUseNoProfiling();
            } else if (profileType.compareToIgnoreCase(EclipseLink_Product_Name) == 0) {
                this.setUseEclipseLinkProfiling();
            }
        }

        /**
        *        This method is used to turn on EclipseLink Performance Profiling
        */
        public void setUseEclipseLinkProfiling() {
            if (getUsesEclipseLinkProfiling()) {
                return;
            }
            getSession().setProfiler(new PerformanceProfiler());
        }


        /**
        *        This method is used to turn off all Performance Profiling, DMS or EclipseLink.
        */
        public void setUseNoProfiling() {
            getSession().setProfiler(null);
        }

       /**
        *        This method answers true if EclipseLink Performance Profiling is on.
        */
        public Boolean getUsesEclipseLinkProfiling() {
            return getSession().getProfiler() instanceof PerformanceProfiler;
        }

        /**
         * PUBLIC: Answer the EclipseLink log level at deployment time. This is read-only.
         */
        public String getDeployedEclipseLinkLogLevel() {
            return getNameForLogLevel(getDeployedSessionLog().getLevel());
        }

        /**
         * PUBLIC: Answer the EclipseLink log level that is changeable.
         * This does not affect the log level in the project (i.e. The next
         * time the application is deployed, changes are forgotten)
         */
        public String getCurrentEclipseLinkLogLevel() {
            return getNameForLogLevel(this.getSession().getSessionLog().getLevel());
        }

        /**
         * PUBLIC: Set the EclipseLink log level to be used at runtime.
         *
         * This does not affect the log level in the project (i.e. The next
         * time the application is deployed, changes are forgotten)
         *
         * @param newLevel new log level
         */
        public synchronized void setCurrentEclipseLinkLogLevel(String newLevel) {
            this.getSession().setLogLevel(this.getLogLevelForName(newLevel));
        }

        /**
         * INTERNAL: Answer the name for the log level given.
         *
         * @return String (one of OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL)
         */
        private String getNameForLogLevel(int logLevel) {
            switch (logLevel) {
            case SessionLog.ALL:
                return SessionLog.ALL_LABEL;
            case SessionLog.SEVERE:
                return SessionLog.SEVERE_LABEL;
            case SessionLog.WARNING:
                return SessionLog.WARNING_LABEL;
            case SessionLog.INFO:
                return SessionLog.INFO_LABEL;
            case SessionLog.CONFIG:
                return SessionLog.CONFIG_LABEL;
            case SessionLog.FINE:
                return SessionLog.FINE_LABEL;
            case SessionLog.FINER:
                return SessionLog.FINER_LABEL;
            case SessionLog.FINEST:
                return SessionLog.FINEST_LABEL;
            case SessionLog.OFF:
                return SessionLog.OFF_LABEL;
            default:
                return "N/A";
            }
        }

        /**
         * INTERNAL: Answer the log level for the given name.
         *
         * @return int for OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL
         */
        private int getLogLevelForName(String levelName) {
            if (levelName.equals(SessionLog.ALL_LABEL)) {
                return SessionLog.ALL;
            }
            if (levelName.equals(SessionLog.SEVERE_LABEL)) {
                return SessionLog.SEVERE;
            }
            if (levelName.equals(SessionLog.WARNING_LABEL)) {
                return SessionLog.WARNING;
            }
            if (levelName.equals(SessionLog.INFO_LABEL)) {
                return SessionLog.INFO;
            }
            if (levelName.equals(SessionLog.CONFIG_LABEL)) {
                return SessionLog.CONFIG;
            }
            if (levelName.equals(SessionLog.FINE_LABEL)) {
                return SessionLog.FINE;
            }
            if (levelName.equals(SessionLog.FINER_LABEL)) {
                return SessionLog.FINER;
            }
            if (levelName.equals(SessionLog.FINEST_LABEL)) {
                return SessionLog.FINEST;
            }
            return SessionLog.OFF;
        }
     /**
      *  INTERNAL:
      *  Define the deployment time data associated with logging and profiling
      *
      */
     protected void updateDeploymentTimeData() {
         this.deployedSessionLog = (SessionLog) session.getSessionLog().clone();
         if (session.getProfiler() == null) {
             this.deployedSessionProfileWeight = -1;//there is no profiler
         } else {
             this.deployedSessionProfileWeight = session.getProfiler().getProfileWeight();
         }
     }

     public int getDeployedSessionProfileWeight() {
         return deployedSessionProfileWeight;
     }

     public SessionLog getDeployedSessionLog() {
         return deployedSessionLog;
     }

     public String getObjectName() {
         return objectName;
     }

     /**
      * Return whether this session is an EclipseLink JPA session.
      * The absence of this function or a value of false will signify that the session
      * belongs to a provider other than EclipseLink.
      */
     public boolean isJPASession() {
         return true;
     }

     /**
      * Answer the type of the EclipseLink session this MBean represents.
      * Types include: "ServerSession", "DatabaseSession", "SessionBroker"
      */
     public String getSessionType() {
         return Helper.getShortClassName(getSession().getClass());
     }

     /**
      * Provide an instance of 2 Dimensional Array simulating tabular format information about all
      * classes in the session whose class names match the provided filter.
      *
      * The 2 Dimensional array contains each item with values being row object array. Each row object array
      * represents EclipseLink class details info with respect to below attributes:
      * ["Class Name", "Parent Class Name",  "Cache Type", "Configured Size", "Current Size"]
      *
      */
     public Object[][] getClassSummaryDetailsUsingFilter(String filter){
         try{
            return  tabularDataTo2DArray(buildClassSummaryDetailsUsingFilter(filter),new String[] {
                "Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" });
         } catch (Exception exception) {
             AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
         }
         return null;
     }

     /**
      * PUBLIC: Provide an instance of 2 Dimensional Array simulating tabular format information about all
      * classes in the session.
      *
      * The 2 Dimensional array contains each item with values being row object array. Each row object array
      * represents EclipseLink class details info with respect to below attributes:
      * ["Class Name", "Parent Class Name",  "Cache Type", "Configured Size", "Current Size"]
      *
      */
     public Object[][] getClassSummaryDetails() {
         try{
            return tabularDataTo2DArray(buildClassSummaryDetails(),new String[] {
                "Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" });
         } catch (Exception exception){
             AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
         }
         return null;
     }

     /**
      * INTERNAL:
      * Answer the fully qualified names of the classes mapped in the session.
      * This uses the mappedClass from the CMPPolicy.
      *
      * @return java.util.Vector
      */
     private Vector<String> getMappedClassNames() {
         Map<String, Boolean> alreadyAdded = new HashMap<>();
         Vector<String> mappedClassNames = new Vector<>();
         String mappedClassName = null;

         Iterator<ClassDescriptor> descriptorsIterator = getSession().getProject().getDescriptors()
                 .values().iterator();
         while (descriptorsIterator.hasNext()) {
             ClassDescriptor nextDescriptor = descriptorsIterator.next();

             // differentiate between a generated class and not, by comparing the descriptor's Java class
             if (nextDescriptor.getCMPPolicy() != null) {
                 if (nextDescriptor.getCMPPolicy().getMappedClass() != null) {
                     mappedClassName = nextDescriptor.getCMPPolicy().getMappedClass().getName();
                 }
             }

             if (mappedClassName == null) {
                 mappedClassName = nextDescriptor.getJavaClassName();
             }
             if (alreadyAdded.get(mappedClassName) == null) {
                 alreadyAdded.put(mappedClassName, Boolean.TRUE);
                 mappedClassNames.addElement(mappedClassName);
             }
             mappedClassName = null;
         }
         return mappedClassNames;
     }

     /**
     *  INTERNAL:
     *  This method traverses the EclipseLink descriptors and returns a Vector of the descriptor's
     *   reference class names that match the provided filter. The filter is a comma separated
     *   list of strings to match against.
     *
     *   @param filter A comma separated list of strings to match against.
     *   @return A Vector of class names that match the filter.
     */
     public Vector<String> getMappedClassNamesUsingFilter(String filter) {
         //Output Vector
         Vector<String> outputVector = new Vector<>();

         //Input mapped class names
         Vector<String> mappedClassNames = getMappedClassNames();

         //Input filter values
         List<String> filters = new ArrayList<>();
         StringTokenizer lineTokens = new StringTokenizer(filter, ",");
         while (lineTokens.hasMoreTokens()) {
             filters.add(lineTokens.nextToken());
         }
         for (int i = 0; i < mappedClassNames.size(); i++) {
             String className = mappedClassNames.get(i);
             String classNameLowerCase = mappedClassNames.get(i).toLowerCase();
             for (int j = 0; j < filters.size(); j++) {
                 String filterValue = (Helper.rightTrimString(filters.get(j)).trim()).toLowerCase();
                 if (filterValue.indexOf('*') == 0) {
                     filterValue = filterValue.substring(1);
                 }
                 try {
                     //Note: String.matches(String regex) since jdk1.4
                     if (classNameLowerCase.matches(new StringBuilder().append("^.*").append(filterValue).append(".*$").toString())) {
                         if (!outputVector.contains(className)) {
                             outputVector.add(className);
                         }
                     }
                 } catch (PatternSyntaxException exception) {
                     //regular expression syntax error
                     AbstractSessionLog.getLog().log(SessionLog.FINEST, "pattern_syntax_error", exception);
                 }
             }
         }
         Collections.sort(outputVector);
         return outputVector;
     }



     /**
      * INTERNAL:
      * getCacheTypeFor: Give a more UI-friendly version of the cache type
      */
     protected String getCacheTypeFor(Class identityMapClass) {
         if (identityMapClass == CacheIdentityMap.class) {
             return "Cache";
         } else if (identityMapClass == FullIdentityMap.class) {
             return "Full";
         } else if (identityMapClass == HardCacheWeakIdentityMap.class) {
             return "HardWeak";
         } else if (identityMapClass == NoIdentityMap.class) {
             return "None";
         } else if (identityMapClass == SoftCacheWeakIdentityMap.class) {
             return "SoftWeak";
         } else if (identityMapClass == WeakIdentityMap.class) {
             return "Weak";
         } else if (identityMapClass == SoftIdentityMap.class) {
             return "Soft";
         }
         return "N/A";
     }

     /**
      * getModuleName(): Answer the name of the context-root of the application that this session is associated with.
      * Answer "unknown" if there is no module name available.
      * Default behavior is to return "unknown" - we override this behavior here for WebLogic.
      */
     public String getModuleName() {
         return getSession()
             .getServerPlatform().getModuleName();
     }


     /**
      * getApplicationName(): Answer the name of the module (EAR name) that this session is associated with.
      * Answer "unknown" if there is no application name available.
      * Default behavior is to return "unknown" - we override this behavior here for all platform implementors of JMXEnabledPlatform
      */
     public String getApplicationName() {
         return ((JMXEnabledPlatform) getSession()
                 .getServerPlatform()).getApplicationName();
     }

     /**
      *     Method returns if all Parameters should be bound or not
      */
     public Boolean getShouldBindAllParameters() {
         if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
             return Boolean.FALSE;
         }
         return ((DatabaseLogin) getSession().getDatasourceLogin()).shouldBindAllParameters();
     }

     /**
       *     Return the size of strings after which will be bound into the statement
       *     If we are not using a DatabaseLogin, or we're not using string binding,
       *     answer 0 (zero).
       */
     public Integer getStringBindingSize() {
         if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
             return 0;
         }
         if (!getSession().getDatasourceLogin().getPlatform().usesStringBinding()) {
             return 0;
         }
         return ((DatabaseLogin) getSession().getDatasourceLogin()).getStringBindingSize();
     }

     /**
       *        This method will return if batchWriting is in use or not.
       */
     public Boolean getUsesBatchWriting() {
         return getSession().getDatasourceLogin().getPlatform().usesBatchWriting();
     }

     /**
       *        This method will return a long indicating the exact time in Milliseconds that the
       *   session connected to the database.
       */
     public Long getTimeConnectionEstablished() {
         return ((DatabaseSessionImpl) getSession()).getConnectedTime();
     }

     /**
       *        This method will return if batchWriting is in use or not.
       */
     public Boolean getUsesJDBCBatchWriting() {
         if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
             return Boolean.FALSE;
         }
         return getSession().getDatasourceLogin().getPlatform().usesJDBCBatchWriting();
     }

     /**
       *     Shows if Byte Array Binding is turned on or not
       */
     public Boolean getUsesByteArrayBinding() {
         if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
             return Boolean.FALSE;
         }
         return getSession().getDatasourceLogin().getPlatform().usesByteArrayBinding();
     }

     /**
       *     Shows if native SQL is being used
       */
     public Boolean getUsesNativeSQL() {
         if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
             return Boolean.FALSE;
         }
         return getSession().getDatasourceLogin().getPlatform().usesNativeSQL();
     }

     /**
       *     This method indicates if streams are being used for binding
       */
     public Boolean getUsesStreamsForBinding() {
         if (!(getSession().getDatasourceLogin().getDatasourcePlatform() instanceof DatabasePlatform)) {
             return Boolean.FALSE;
         }
         return getSession().getDatasourceLogin().getPlatform().usesStreamsForBinding();
     }

     /**
       *     This method indicates if Strings are being bound
       */
     public Boolean getUsesStringBinding() {
         if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
             return Boolean.FALSE;
         }
         return getSession().getDatasourceLogin().getPlatform().usesStringBinding();
     }

     /**
     *     Returns if statements should be cached or not
     */
     public boolean getShouldCacheAllStatements() {
         if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
             return Boolean.FALSE;
         }
         return ((DatabaseLogin) getSession().getDatasourceLogin()).shouldCacheAllStatements();
     }

     /**
     *     Used to clear the statement cache. Only valid if statements are being cached
     */
     public synchronized void clearStatementCache() {
         if (!(getSession().getDatasourceLogin() instanceof DatabaseLogin)) {
             return;
         }
         ((DatabaseAccessor)getSession().getAccessor()).clearStatementCache(getSession());
         ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_statement_cache_cleared");

     }

     /**
     *     This method will print the available Connection pools to the SessionLog.
     */
     public void printAvailableConnectionPools() {
         if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
             Map<String, ConnectionPool> pools = ((ServerSession)getSession()).getConnectionPools();
             Iterator<String> poolNames = pools.keySet().iterator();
             while (poolNames.hasNext()) {
                 String poolName = poolNames.next().toString();
                 ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_pool_name", poolName);
             }
         } else {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_connection_pools_available");

         }
     }

     /**
     *     This method will retrieve the max size of a particular connection pool
     * @param poolName the name of the pool to get the max size for
     * @return Integer for the max size of the pool. Return -1 if pool doesn't exist.
     */
     public Integer getMaxSizeForPool(String poolName) {
         if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
             ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
             if (connectionPool != null) {
                 return connectionPool.getMaxNumberOfConnections();
             }
         }
         return -1;
     }

     /**
     *     This method will retrieve the min size of a particular connection pool
     * @param poolName the name of the pool to get the min size for
     * @return Integer for the min size of the pool. Return -1 if pool doesn't exist.
     */
     public Integer getMinSizeForPool(String poolName) {
         if (ClassConstants.ServerSession_Class.isAssignableFrom(getSession().getClass())) {
             ConnectionPool connectionPool = ((ServerSession)getSession()).getConnectionPool(poolName);
             if (connectionPool != null) {
                 return connectionPool.getMinNumberOfConnections();
             }
         }
         return -1;
     }

     /**
     *        This method is used to output those Class Names that have identity Maps in the Session.
     * Please note that SubClasses and aggregates will be missing from this list as they do not have
     * separate identity maps.
     */
     public void printClassesInSession() {
         Vector classes = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
         int index;
         if (classes.isEmpty()) {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_classes_in_session");
             return;
         }

         for (index = 0; index < classes.size(); index++) {
             getSession().getSessionLog().log(SessionLog.FINEST, (String)classes.elementAt(index));
         }
     }

     /**
     *        This method will log the objects in the Identity Map.
     * There is no particular order to these objects.
     * @param className the fully qualified classname identifying the identity map
     * @exception ClassNotFoundException thrown then the IdentityMap for that class name could not be found
     */
     public void printObjectsInIdentityMap(String className) throws ClassNotFoundException {
         Class classWithMap = getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
         IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classWithMap);

         //check if the identity map exists
         if (null == map) {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_non_existent", className);
             return;
         }

         //check if there are any objects in the identity map. Print if so.
         Enumeration<CacheKey> objects = map.keys();
         if (!objects.hasMoreElements()) {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_empty", className);
         }

         CacheKey cacheKey;
         while (objects.hasMoreElements()) {
             cacheKey = objects.nextElement();
             if(null != cacheKey && null != cacheKey.getKey() && null != cacheKey.getObject()) {
                 ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_print_cache_key_value",
                     cacheKey.getKey().toString(), cacheKey.getObject().toString());
             }
         }
     }

     /**
     *        This method will log the types of Identity Maps in the session.
     */
     public void printAllIdentityMapTypes() {
         Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
         String registeredClassName;
         Class registeredClass;

         //Check if there aren't any classes registered
         if (classesRegistered.size() == 0) {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
             return;
         }

         //get each identity map, and log the type
         for (int index = 0; index < classesRegistered.size(); index++) {
             registeredClassName = (String)classesRegistered.elementAt(index);
             registeredClass = getSession().getDatasourcePlatform().getConversionManager().convertObject(registeredClassName, ClassConstants.CLASS);
             IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(registeredClass);
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_class",
                     registeredClassName, map.getClass());
         }
     }

     /**
     *        This method will log all objects in all Identity Maps in the session.
     */
     public void printObjectsInIdentityMaps() {
         Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
         String registeredClassName;

         //Check if there aren't any classes registered
         if (classesRegistered.size() == 0) {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
             return;
         }

         //get each identity map, and log the type
         for (int index = 0; index < classesRegistered.size(); index++) {
             registeredClassName = (String)classesRegistered.elementAt(index);
             try {
                 this.printObjectsInIdentityMap(registeredClassName);
             } catch (ClassNotFoundException classNotFound) {
                 //we are enumerating registered classes, so this shouldn't happen. Print anyway
                 classNotFound.printStackTrace();
                 AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, classNotFound);
             }
         }
     }

     /**
     *        This method will SUM and return the number of objects in all Identity Maps in the session.
     */
     public Integer getNumberOfObjectsInAllIdentityMaps() {
         Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
         String registeredClassName;
         int sum = 0;

         //Check if there aren't any classes registered
         if (classesRegistered.size() == 0) {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
             return 0;
         }

         //get each identity map, and log the size
         for (int index = 0; index < classesRegistered.size(); index++) {
             registeredClassName = (String)classesRegistered.elementAt(index);
             try {
                 sum += this.getNumberOfObjectsInIdentityMap(registeredClassName);
             } catch (ClassNotFoundException classNotFound) {
                 //we are enumerating registered classes, so this shouldn't happen. Print anyway
                 classNotFound.printStackTrace();
                 AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, classNotFound);
             }
         }

         return sum;
     }

     /**
      * This method will answer the number of persistent classes contained in the session.
      * This does not include aggregates.
      */
     public Integer getNumberOfPersistentClasses() {
         Map classesTable = new HashMap();
         ClassDescriptor currentDescriptor;

         //use a table to eliminate duplicate classes. Ignore Aggregates
         Iterator<ClassDescriptor> descriptors = getSession().getProject().getDescriptors().values().iterator();
         while (descriptors.hasNext()) {
             currentDescriptor = descriptors.next();
             if (!currentDescriptor.isAggregateDescriptor()) {
                 classesTable.put(currentDescriptor.getJavaClassName(), Boolean.TRUE);
             }
         }

         return classesTable.size();
     }

     /**
     * Return the log type, either "EclipseLink",  "Java" or the simple name of the logging class used.
     *
     * @return the log type
     */
     public String getLogType() {
         if (this.getSession().getSessionLog().getClass() == JavaLog.class) {
             return "Java";
         } else if (this.getSession().getSessionLog().getClass() == DefaultSessionLog.class) {
             return EclipseLink_Product_Name;
         } else {
             return this.getSession().getSessionLog().getClass().getSimpleName();
         }
     }

     /**
     * Return the database platform used by the DatabaseSession.
     *
     * @return String databasePlatform
     */
     public String getDatabasePlatform() {
         return getSession().getDatasourcePlatform().getClass().getName();
     }

     /**
     *        Return JDBCConnection detail information. This includes URL and datasource information.
     */
     public synchronized String getJdbcConnectionDetails() {
         return getSession().getLogin().getConnector().getConnectionDetails();
     }

     /**
     *        Return connection pool type. Values include: "Internal", "External" and "N/A".
     */
     public synchronized String getConnectionPoolType() {
         if (getSession().getLogin().shouldUseExternalConnectionPooling()) {
             return "External";
         } else {
             return "N/A";
         }
     }

     /**
     *        Return db driver class name. This only applies to DefaultConnector. Return "N/A" otherwise.
     */
     public synchronized String getDriver() {
         if (getSession().getLogin().getConnector() instanceof DefaultConnector) {
             return getSession().getLogin().getDriverClassName();
         }
         return "N/A";
     }

     /**
     * Return the log filename. This returns the fully qualified path of the log file when
     * EclipseLink DefaultSessionLog instance is used. Null is returned otherwise.
     *
     * @return String logFilename
     */
     public String getLogFilename() {
         // returns String or null.
         if ( session.getSessionLog() instanceof DefaultSessionLog) {
                 return ((DefaultSessionLog)session.getSessionLog()).getWriterFilename();
         } else {
             return null;
         }
     }

     /**
     *    This method is used to initialize the identity maps in the session.
     */
     public synchronized void initializeAllIdentityMaps() {
         getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
     }

     /**
     *    This method is used to initialize the identity maps specified by the Vector of classNames.
     *
     * @param classNames String[] of fully qualified classnames identifying the identity maps to initialize
     */
     public synchronized void initializeIdentityMaps(String[] classNames) throws ClassNotFoundException {
         for (int index = 0; index < classNames.length; index++) {
             initializeIdentityMap(classNames[index]);
         }
     }

     /**
     *    This method is used to invalidate the identity maps in the session.
     */
     public synchronized void invalidateAllIdentityMaps() {
         Vector classesRegistered = getSession().getIdentityMapAccessorInstance().getIdentityMapManager().getClassesRegistered();
         String registeredClassName;
         Class registeredClass;

         if (classesRegistered.isEmpty()) {
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_no_identity_maps_in_session");
         }

         //get each identity map, and invalidate
         for (int index = 0; index < classesRegistered.size(); index++) {
             registeredClassName = (String)classesRegistered.elementAt(index);
             registeredClass = getSession().getDatasourcePlatform().getConversionManager()
                 .convertObject(registeredClassName, ClassConstants.CLASS);
             getSession().getIdentityMapAccessor().invalidateClass(registeredClass);
             ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_invalidated", registeredClassName);
         }
     }

     /**
     *    This method is used to invalidate the identity maps specified by the String[] of classNames.
     *
     * @param classNamesParam String[] of fully qualified classnames identifying the identity maps to invalidate
     * @param recurse    Boolean indicating if we want to invalidate the children identity maps too
     */
     public synchronized void invalidateIdentityMaps(String[] classNamesParam, Boolean recurse) throws ClassNotFoundException {
         String[] classNames = classNamesParam;
         for (int index = 0; index < classNames.length; index++) {
             invalidateIdentityMap(classNames[index], recurse);
         }
     }

     /**
     *    This method is used to invalidate the identity maps specified by className. This does not
     * invalidate the children identity maps
     *
     * @param className the fully qualified classname identifying the identity map to invalidate
     */
     public synchronized void invalidateIdentityMap(String className) throws ClassNotFoundException {
         this.invalidateIdentityMap(className, Boolean.FALSE);
     }

     /**
     *    This method is used to invalidate the identity maps specified by className.
     *
     * @param className the fully qualified classname identifying the identity map to invalidate
     * @param recurse    Boolean indicating if we want to invalidate the children identity maps too
     */
     public synchronized void invalidateIdentityMap(String className, Boolean recurse) throws ClassNotFoundException {
         Class registeredClass;

         //get identity map, and invalidate
         registeredClass = getSession().getDatasourcePlatform().getConversionManager()
             .convertObject(className, ClassConstants.CLASS);
         getSession().getIdentityMapAccessor().invalidateClass(registeredClass);
         ((AbstractSession)session).log(SessionLog.INFO, SessionLog.SERVER, "jmx_mbean_runtime_services_identity_map_invalidated", className);
     }

     /**
      *
     * INTERNAL:
      * Convert the TabularData to a two-dimensional array
      * @param tdata the TabularData to be converted
      * @param names the order of the columns
      * @return a two-dimensional array
      */
     private Object[][] tabularDataTo2DArray(TabularData tdata, String[] names) throws Exception {
         if(tdata==null){
             return null;
         }
         Object[] rows = tdata.values().toArray();
         Object[][] data = new Object[rows.length][];

         for (int i = 0; i < rows.length; i++) {
             CompositeData cdata = ((CompositeData) rows[i]);
             Object[] returnRow = new Object[names.length];
             for (int j = 0; j < names.length; j++) {
                 String name = names[j];
                 Object value = cdata.get(name);
                 returnRow[j] = name + " : " + String.valueOf(value);
             }
             data[i] = returnRow;
         }
         return data;
     }

     /**
      *  INTERNAL:
      *  Define the session that this instance is providing runtime services for
      *
      *  @param newSession The session to be used with these RuntimeServices
      */
     protected void setSession(AbstractSession newSession) {
         this.session = newSession;
         this.updateDeploymentTimeData();
     }

     /**
      * INTERNAL:
      * Answer the CompositeType describing the CompositeData that we return for
      * each IdentityMap (or subclass).
      *
      * This is mostly for the client side to see what kind of information is returned.
      * @return javax.management.openmbean.CompositeType
      */
     private CompositeType buildCompositeTypeForClassSummaryDetails() throws OpenDataException {
         return new CompositeType("Class Details", "Details of class for Class Summary", new String[] {
                 "Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" }, new String[] {
                 "Class Name", "Parent Class Name", "Cache Type", "Configured Size", "Current Size" }, new OpenType[] {
                 SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING });
     }


     /**
      * Provide a list of instance of ClassSummaryDetail containing information about the
      * classes in the session whose class names match the provided filter.
      *
      * ClassSummaryDetail is a model specific class that can be used internally by the Portable JMX Framework to
      * convert class attribute to JMX required open type, it has:-
      *    1. model specific type that needs to be converted : ["Class Name", "Parent Class Name",  "Cache Type", "Configured Size", "Current Size"]
      *    2. convert methods.
      *
      * @param filter A comma separated list of strings to match against.
      * @return A ArrayList of instance of ClassSummaryDetail containing class information for the class names that match the filter.
      */
     public List<ClassSummaryDetailBase>  getClassSummaryDetailsUsingFilterArray(String filter) {
         try {
             // if the filter is null, return all the details
             Vector<String> mappedClassNames = getMappedClassNamesUsingFilter(filter);
             String mappedClassName;
             List<ClassSummaryDetailBase> classSummaryDetails = new ArrayList<>();
             // Check if there aren't any classes mapped
             if (mappedClassNames.size() == 0) {
                 return null;
             }
             CompositeType type = buildCompositeTypeForClassSummaryDetails();
             // get details for each class, and add the details to the summary
             for (int index = 0; index < mappedClassNames.size(); index++) {
                 mappedClassName = mappedClassNames.elementAt(index);
                 Map<String, String> data = buildLowlevelDetailsFor(mappedClassName);
                 final CompositeDataSupport support = new CompositeDataSupport(type, buildLowlevelDetailsFor(mappedClassName));
                 classSummaryDetails.add(ClassSummaryDetailBase.from(support));
             }
             return classSummaryDetails;
         } catch (Exception openTypeException) {
             AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, openTypeException);
             openTypeException.printStackTrace();
         }

         // wait to get requirements from EM
         return null;
     }

     /**
      * Provide a list of instance of ClassSummaryDetail containing information about all
      * classes in the session.
      *
      * ClassSummaryDetail is a model specific class that can be used internally by the Portable JMX Framework to
      * convert class attribute to JMX required open type, it has:-
      *    1. model specific type that needs to be converted : ["Class Name", "Parent Class Name",  "Cache Type", "Configured Size", "Current Size"]
      *    2. convert methods.
      *
      * @return A List of instance of ClassSummaryDetail objects containing class information for the class names that match the filter.
      */
     public List<ClassSummaryDetailBase> getClassSummaryDetailsArray() {
         // wait to get requirements from EM
         return getClassSummaryDetailsUsingFilterArray(".*");
     }

     /**
      * INTERNAL:
      * Answer the TabularType describing the TabularData that we return from
      * getCacheSummaryDetails() and getCacheSummaryDetails(String filter)
      *
      * This is mostly for the client side to see what kind of information is returned.
      *
      * @return javax.management.openmbean.TabularType
      */
     private TabularType buildTabularTypeForClassSummaryDetails() throws OpenDataException {
         return new TabularType(getSessionName(), "Session description", buildCompositeTypeForClassSummaryDetails(),
                 new String[] { "Class Name" });
     }


     /**
      * INTERNAL:
      * Answer the CompositeData containing the cache details for the given mappedClassName
      * This uses a CompositeDataSupport, which implements CompositeData
      *
      * @param mappedClassName fullyQualified class name of the class
      * @param detailsType describes the format of the returned CompositeData

      * @return javax.management.openmbean.CompositeData
      */
     private CompositeData buildDetailsFor(String mappedClassName, CompositeType detailsType) throws Exception {
         return new CompositeDataSupport(detailsType, buildLowlevelDetailsFor(mappedClassName));
     }

     /**
      * INTERNAL:
      * Helper to build a HashMap to help in the construction of a CompositeData
      *
      * @param mappedClassName fullyQualified class name of the class

      * @return HashMap
      */
     private Map<String, String> buildLowlevelDetailsFor(String mappedClassName) {
         Class mappedClass = getSession().getDatasourcePlatform().getConversionManager().convertObject(mappedClassName, ClassConstants.CLASS);
         ClassDescriptor descriptor = getSession().getProject().getDescriptor(mappedClass);

         String cacheType = "";
         String configuredSize = "";
         String currentSize = "";
         String parentClassName = "";

         // Aggregate descriptors do not have an IdentityMap
         if (!descriptor.isAggregateDescriptor()) {
             IdentityMap identityMap = getSession().getIdentityMapAccessorInstance().getIdentityMap(descriptor);
             cacheType = getCacheTypeFor(identityMap.getClass());
             configuredSize = String.valueOf(identityMap.getMaxSize());
             //show the current size, including subclasses
             currentSize = String.valueOf(identityMap.getSize(mappedClass, true));
         }

         //If I have a parent class name, get it. Otherwise, leave blank
         if (descriptor.hasInheritance()) {
             if (descriptor.getInheritancePolicy().getParentDescriptor() != null) {
                 parentClassName = descriptor.getInheritancePolicy().getParentClassName();
             }
         }

         boolean isChildDescriptor = descriptor.isChildDescriptor();

         Map<String, String> details = new HashMap<>(5);
         details.put("Class Name", mappedClassName);
         details.put("Cache Type", (isChildDescriptor ? "" : cacheType));
         details.put("Configured Size", (isChildDescriptor ? "" : configuredSize));
         details.put("Current Size", currentSize);
         details.put("Parent Class Name", parentClassName);

         return details;
     }


     /**
      * INTERNAL:
      * Provide an instance of TabularData containing information about the
      * classes in the session whose class names match the provided filter.
      *
      * The TabularData contains rowData with values being CompositeData(s)
      *
      * CompositeData has:
      *    CompositeType: column names are ["Class Name", "Parent Class Name",  "Cache Type", "Configured Size", "Current Size"]
      *
      *  Each CompositeData can have get(myColumnName) sent to it.
      *
      *
      * @param filter A comma separated list of strings to match against.
      * @return A TabularData of information for the class names that match the filter.
      */
     private TabularData buildClassSummaryDetailsUsingFilter(String filter) {
         // if the filter is null, return all the details
         if (filter == null) {
             return buildClassSummaryDetails();
         }

         try {
             Vector<String> mappedClassNames = getMappedClassNamesUsingFilter(filter);
             String mappedClassName;
             TabularDataSupport rowData = new TabularDataSupport(buildTabularTypeForClassSummaryDetails());
             // Check if there aren't any classes mapped
             if (mappedClassNames.size() == 0) {
                 return null;
             }

             // get details for each class, and add the details to the summary
             for (int index = 0; index < mappedClassNames.size(); index++) {
                 mappedClassName = mappedClassNames.elementAt(index);
                 String[] key = new String[] { mappedClassName };
                 rowData.put(key, buildDetailsFor(mappedClassName, rowData.getTabularType().getRowType()));
             }
             return rowData;
         } catch (Exception exception) {
             AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
         }

         // wait to get requirements from EM
         return null;
     }

     /**
      * INTERNAL:
      * Provide an instance of TabularData containing information about all
      * classes in the session.
      *
      * The TabularData contains rowData with values being CompositeData(s)
      *
      * CompositeData has:
      *    CompositeType: column names are ["Class Name", "Parent Class Name",  "Cache Type", "Configured Size", "Current Size"]
      *
      *  Each CompositeData can have get(myColumnName) sent to it.
      *
      */
     private TabularData buildClassSummaryDetails() {
         try {
             Vector<String> mappedClassNames = getMappedClassNames();
             String mappedClassName;
             TabularDataSupport rowData = new TabularDataSupport(buildTabularTypeForClassSummaryDetails());
             // Check if there aren't any classes mapped
             if (mappedClassNames.size() == 0) {
                 return null;
             }

             // get details for each class, and add the details to the summary
             for (int index = 0; index < mappedClassNames.size(); index++) {
                 mappedClassName = mappedClassNames.elementAt(index);
                 String[] key = new String[] { mappedClassName };
                 rowData.put(key, buildDetailsFor(mappedClassName, rowData.getTabularType().getRowType()));
             }

             return rowData;
         } catch (Exception exception) {
             AbstractSessionLog.getLog().log(SessionLog.SEVERE, "jmx_enabled_platform_mbean_runtime_exception", PLATFORM_NAME, exception);
         }

         // wait to get requirements from EM
         return null;
     }
}
