/*
 * 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 pools = ((ServerSession)getSession()).getConnectionPools();
            list = new Vector(pools.size());
            Iterator 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 enumtr = ((ServerSession)getSession()).getConnectionPools().values().iterator();
            while (enumtr.hasNext()) {
                ConnectionPool pool = (ConnectionPool)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 = (Class)getSession().getDatasourcePlatform().getConversionManager().convertObject(className, ClassConstants.CLASS);
        IdentityMap map = getSession().getIdentityMapAccessorInstance().getIdentityMap(classToChange);

        Vector results = new Vector(map.getSize());
        Enumeration objects = map.keys();
        while (objects.hasMoreElements()) {
            results.add(((CacheKey)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 = (Class)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 = (Class)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 = (Class)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 = (Class)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 = (Class)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 getMappedClassNames() {
         Map alreadyAdded = new HashMap();
         Vector mappedClassNames = new Vector();
         String mappedClassName = null;

         Iterator descriptorsIterator = getSession().getProject().getDescriptors()
                 .values().iterator();
         while (descriptorsIterator.hasNext()) {
             ClassDescriptor nextDescriptor = (ClassDescriptor) 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 getMappedClassNamesUsingFilter(String filter) {
         //Output Vector
         Vector outputVector = new Vector();

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

         //Input filter values
         ArrayList 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 = (String)mappedClassNames.get(i);
             String classNameLowerCase = ((String)mappedClassNames.get(i)).toLowerCase();
             for (int j = 0; j < filters.size(); j++) {
                 String filterValue = (Helper.rightTrimString((String)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 pools = ((ServerSession)getSession()).getConnectionPools();
             Iterator 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 = (Class)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 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 = (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 = (Class)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 descriptors = getSession().getProject().getDescriptors().values().iterator();
         while (descriptors.hasNext()) {
             currentDescriptor = (ClassDescriptor)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 = (Class)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 = (Class)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.
      */
     /**
      * 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) {
         // if the filter is null, return all the details
         if (filter == null) {
             return getClassSummaryDetailsArray();
         }

         try {
             Vector mappedClassNames = getMappedClassNamesUsingFilter(filter);
             String mappedClassName;
             List classSummaryDetails = new ArrayList<ClassSummaryDetailBase>();
             // 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 = (String)mappedClassNames.elementAt(index);
                 classSummaryDetails.add(buildLowlevelDetailsFor(mappedClassName));
             }
             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() {
         try {
             Vector mappedClassNames = getMappedClassNames();
             List classSummaryDetails = new ArrayList<ClassSummaryDetailBase>();
             // 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++) {
                 String mappedClassName = (String)mappedClassNames.elementAt(index);
                 classSummaryDetails.add(buildLowlevelDetailsFor(mappedClassName));
             }

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

     /**
      * 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 HashMap buildLowlevelDetailsFor(String mappedClassName) {
         Class mappedClass = (Class)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();

         HashMap 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 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 = (String)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 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 = (String)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;
     }
}
