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

// Contributors:
//     06/30/2010-2.1.1 Michael O'Brien
//       - 316513: Enable JMX MBean functionality for JBoss, Glassfish and WebSphere in addition to WebLogic
//       Move JMX MBean generic registration code up from specific platforms
//       see <link>http://wiki.eclipse.org/EclipseLink/DesignDocs/316513</link>
//     07/15/2010-2.1.1 Michael O'Brien
//       - 316513: registration/deregistration mismatch for MBean Object name reg=- and dereg=_ - no more instance already exists on redeploy
//     10/18/2010-2.1.2 Michael O'Brien
//       - 328006: Refactor WebLogic MBeanServer registration to use active
//         WLS com.bea server when multiple instances returned
//       see <link>http://wiki.eclipse.org/EclipseLink/DesignDocs/316513#DI_4:_20100624:_Verify_correct_MBeanServer_available_when_running_multiple_MBeanServer_Instances</link>
//     01/01/2011-2.2 Michael O'Brien
//       - 333160: ModuleName string extraction code does not handle -1 not found index in 3 of 5 cases
//     11/01/2011-2.2 Michael O'Brien
//       - 333336: findMBeanServer() requires security API AccessController.doPrivileged()
//         private run method security block.
//     07/28/2017-2.7 Dalia Abo Sheasha
//       - 520316: Multiple MBeanServers discovered by EclipseLink result in warnings
package org.eclipse.persistence.platform.server;

import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.List;

import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;

import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.services.mbean.MBeanDevelopmentServices;
import org.eclipse.persistence.services.mbean.MBeanRuntimeServicesMBean;
import org.eclipse.persistence.sessions.DatabaseSession;

/**
 * PUBLIC:
 * Subclass of org.eclipse.persistence.platform.server.ServerPlatformBase
 * in support of the JMXEnabledPlatform interface
 * <p>
 * This is the abstract superclass of all platforms for all servers that contain a subclass
 * that implements the JMXEnabledPlatform interface.
 * Each DatabaseSession
 * contains an instance of the receiver, to help the DatabaseSession determine:
 * <ul>
 * <li> Whether or not to enable JTA (external transaction control)
 * <li> How to register/unregister for runtime services (JMX/MBean)
 * <li> Whether or not to enable runtime services
 * </ul><p>
 * Subclasses already exist to provide configurations for Oc4J, WebLogic, JBoss, NetWeaver, GlassFish and WebSphere.
 * <p>
 * If the versioned platform subclass is JMX enabled by EclipseLink (registers MBeans) then that
 * server platform must implement the JMXEnabledPlatform interface
 * To provide some different behavior than the provided ServerPlatform(s), we recommend
 * subclassing org.eclipse.persistence.platform.server.JMXServerPlatformBase (or a subclass),
 * and overriding:
 * <ul>
 * <li>JMXEnabledPlatform.prepareServerSpecificServicesMBean()
 * </ul>
 * for the desired behavior.
 *
 * @see org.eclipse.persistence.platform.server.ServerPlatformBase
 * @since EclipseLink 2.1.1
 */
public abstract class JMXServerPlatformBase extends ServerPlatformBase {
    /** This JNDI address is for JMX MBean registration */
    private static final String JMX_JNDI_RUNTIME_REGISTER = "java:comp/env/jmx/runtime";
    /*
     * If the cached MBeanServer is not used, then the unregister jndi address must be used to create a context
     * Note: the context must be explicitly closed after use or we may cache the user and get a
     * weblogic.management.NoAccessRuntimeException when trying to use the associated MBeanServer
     * see http://bugs.eclipse.org/238343
     * see http://e-docs.bea.com/wls/docs100/jndi/jndi.html#wp467275
     */
    /** This JNDI address is for JMX MBean unregistration */
    private static final String JMX_JNDI_RUNTIME_UNREGISTER = "java:comp/jmx/runtime";

    /** This is the prefix for all MBeans that are registered with their specific session name appended */
    public static final String JMX_REGISTRATION_PREFIX = "TopLink:Name=";
    /** The default indexed MBeanServer instance to use when multiple MBeanServer instances exist on the platform - usually only in JBoss */
    public static final int JMX_MBEANSERVER_INDEX_DEFAULT_FOR_MULTIPLE_SERVERS = 0;
    /** This persistence.xml or sessions.xml property is used to override the moduleName */
    protected static final String OVERRIDE_JMX_MODULENAME_PROPERTY = "eclipselink.jmx.moduleName";
    /** This persistence.xml or sessions.xml property is used to override the applicationName */
    protected static final String OVERRIDE_JMX_APPLICATIONNAME_PROPERTY = "eclipselink.jmx.applicationName";

    /**
     * The following constants and attributes are used to determine the module and application name
     * to satisfy the requirements for 248746 where we provide an identifier pair for JMX sessions.
     * Each application can have several modules.
     * 1) Application name - the persistence unit associated with the session (a 1-1 relationship)
     * 2) Module name - the ejb or war jar name (there is a 1-many relationship for module:session(s))
     */
    /** Override by subclass: Search String in application server ClassLoader for the application:persistence_unit name */
    private static String APP_SERVER_CLASSLOADER_OVERRIDE_DEFAULT = "postfix,match~should;be]implemented!by`subclass^";
    protected static String APP_SERVER_CLASSLOADER_APPLICATION_PU_SEARCH_STRING_PREFIX = APP_SERVER_CLASSLOADER_OVERRIDE_DEFAULT;
    protected static String APP_SERVER_CLASSLOADER_APPLICATION_PU_SEARCH_STRING_POSTFIX = APP_SERVER_CLASSLOADER_OVERRIDE_DEFAULT;

    /** Override by subclass: Search String in application server session for ejb modules */
    protected static String APP_SERVER_CLASSLOADER_MODULE_EJB_SEARCH_STRING_PREFIX = APP_SERVER_CLASSLOADER_OVERRIDE_DEFAULT;
    /** Override by subclass: Search String in application server session for war modules */
    protected static String APP_SERVER_CLASSLOADER_MODULE_WAR_SEARCH_STRING_PREFIX = APP_SERVER_CLASSLOADER_OVERRIDE_DEFAULT;
    protected static String APP_SERVER_CLASSLOADER_MODULE_EJB_WAR_SEARCH_STRING_POSTFIX = APP_SERVER_CLASSLOADER_OVERRIDE_DEFAULT;


    /** Cache the ServerPlatform MBeanServer for performance */
    protected MBeanServer mBeanServer = null;

    /** cache the RuntimeServices MBean - during platform construction for JMXEnabledPlatform implementors */
    private MBeanRuntimeServicesMBean runtimeServicesMBean = null;

    /** moduleName determination is available during MBean registration only */
    private String moduleName = null;

    /** applicationName determination is available during MBean registration only */
    private String applicationName = null;

    /**
     * INTERNAL:
     * Default Constructor: Initialize so that runtime services and JTA are enabled.
     *
     * @param newDatabaseSession The instance of DatabaseSession that I am helping.
     */
    protected JMXServerPlatformBase(DatabaseSession newDatabaseSession) {
        super(newDatabaseSession);
    }

    /**
     * Return the AbstractSession required to log to the non-platform EclipseLink log.
     * Note: The WeblogicEclipseLinkLog  defined for the WebLogic platform currently only supports the following
     * logging categories in the categoryMap HashMap
     * {connection=DebugJpaJdbcJdbc,
     * cache=DebugJpaDataCache,
     * transaction=DebugJpaJdbcJdbc,
     * weaver=DebugJpaEnhance,
     * query=DebugJpaQuery,
     * dms=DebugJpaProfile,
     * sequencing=DebugJpaRuntime,
     * properties=DebugJpaRuntime,
     * ejb=DebugJpaRuntime,
     * jpa_metamodel=DebugJpaMetaData,
     * sql=DebugJpaJdbcSql,
     * ejb_or_metadata=DebugJpaMetaData,
     * event=DebugJpaRuntime,
     * server=DebugJpaRuntime,
     * propagation=DebugJpaDataCache}
     */
    protected AbstractSession getAbstractSession() {
        return ((AbstractSession)getDatabaseSession());
    }

    /**
     * INTERNAL:
     * Return the MBeanServer to be used for MBean registration and deregistration.<br>
     * This MBeanServer reference is lazy loaded and cached on the platform.<br>
     * There are multiple ways of getting the MBeanServer<br>
     * <p>
     * 1) MBeanServerFactory static function - working for 3 of 4 servers  WebSphere, JBoss and Glassfish in a generic way<br>
     *   - JBoss returns 2 MBeanServers in the List - but one of them has a null domain - we don't use that one<br>
     *   - WebLogic may return 2 MBeanServers - in that case we want to register with the one containing the "com.bea" tree
     * 2) ManagementFactory static function - what is the difference in using this one over the one returning a List of servers<br>
     * 3) JNDI lookup<br>
     * 4) Direct server specific native API<br></p>
     * We are using method (1)<br>
     *
     * @return the JMX specification MBeanServer
     */
    public MBeanServer getMBeanServer() {
        /**
         * This function will attempt to get the MBeanServer via the findMBeanServer spec call.
         * 1) If the return list is null we attempt to retrieve the PlatformMBeanServer
         * (if it exists or is enabled in this security context).
         * 2) If the list of MBeanServers returned is more than one
         * we get the lowest indexed MBeanServer that does not on a null default domain.
         * 3) 333336: we need to wrap JMX calls in doPrivileged blocks
         * 4) fail-fast: if there are any issues with JMX - continue - don't block the deploy()
         */
        // lazy initialize the MBeanServer reference
        if(null == mBeanServer) {
            List<MBeanServer> mBeanServerList = null;
            try {
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    try {
                        mBeanServerList = (List<MBeanServer>) AccessController.doPrivileged(
                            new PrivilegedExceptionAction() {
                                @Override
                                public List<MBeanServer> run() {
                                    return MBeanServerFactory.findMBeanServer(null);
                                }
                            }
                           );
                    } catch (PrivilegedActionException pae) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER,
                                "failed_to_find_mbean_server", "null or empty List returned from privileged MBeanServerFactory.findMBeanServer(null)");
                        Context initialContext = null;
                        try {
                            initialContext = new InitialContext(); // the context should be cached
                            mBeanServer = (MBeanServer) initialContext.lookup(JMX_JNDI_RUNTIME_REGISTER);
                        } catch (NamingException ne) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "failed_to_find_mbean_server", ne);
                        }
                    }
                } else {
                    mBeanServerList = MBeanServerFactory.findMBeanServer(null);
                }
                // Attempt to get the first MBeanServer we find - usually there is only one - when agentId == null we return a List of them
                if(null == mBeanServer && (null == mBeanServerList || mBeanServerList.isEmpty())) {
                    // Unable to acquire a JMX specification List of MBeanServer instances
                    getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER,
                            "failed_to_find_mbean_server", "null or empty List returned from MBeanServerFactory.findMBeanServer(null)");
                    // Try alternate static method
                    if (!PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                        mBeanServer = ManagementFactory.getPlatformMBeanServer();
                        if(null == mBeanServer) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER,
                                "failed_to_find_mbean_server", "null returned from ManagementFactory.getPlatformMBeanServer()");
                        } else {
                            getAbstractSession().log(SessionLog.FINER, SessionLog.SERVER,
                                    "jmx_mbean_runtime_services_registration_mbeanserver_print",
                                    new Object[]{mBeanServer, mBeanServer.getMBeanCount(), mBeanServer.getDefaultDomain(), 0});
                        }
                    }
                } else {
                    // Use the first MBeanServer by default - there may be multiple domains each with their own MBeanServer
                    mBeanServer = mBeanServerList.get(JMX_MBEANSERVER_INDEX_DEFAULT_FOR_MULTIPLE_SERVERS);
                    if(mBeanServerList.size() > 1) {
                        // There are multiple MBeanServerInstances (usually only JBoss)
                        // 328006: WebLogic may also return multiple instances (we need to register the one containing the com.bea tree)
                        getAbstractSession().log(SessionLog.INFO, SessionLog.SERVER,
                                "jmx_mbean_runtime_services_registration_encountered_multiple_mbeanserver_instances",
                                mBeanServerList.size(), JMX_MBEANSERVER_INDEX_DEFAULT_FOR_MULTIPLE_SERVERS, mBeanServer);
                        // IE: for JBoss we need to verify we are using the correct MBean server of the two (default, null)
                        // Check the domain if it is non-null - avoid using this server
                        int index = 0;
                        for(MBeanServer anMBeanServer : mBeanServerList) {
                            getAbstractSession().log(SessionLog.FINER, SessionLog.SERVER,
                                    "jmx_mbean_runtime_services_registration_mbeanserver_print",
                                    new Object[]{anMBeanServer, anMBeanServer.getMBeanCount(), anMBeanServer.getDefaultDomain(), index});
                            if(null != anMBeanServer.getDefaultDomain()) {
                                mBeanServer = anMBeanServer;
                                getAbstractSession().log(SessionLog.INFO, SessionLog.SERVER,
                                        "jmx_mbean_runtime_services_switching_to_alternate_mbeanserver",
                                        mBeanServer, index);
                            }
                            index++;
                        }
                    } else {
                        // Only a single MBeanServer instance was found
                        getAbstractSession().log(SessionLog.FINER, SessionLog.SERVER,
                                "jmx_mbean_runtime_services_registration_mbeanserver_print",
                                new Object[]{mBeanServer, mBeanServer.getMBeanCount(), mBeanServer.getDefaultDomain(), 0});
                    }
                }
            } catch (Exception e) {
                // TODO: Warning required
                e.printStackTrace();
            }
        }
        return mBeanServer;
    }

    /**
     * INTERNAL: serverSpecificRegisterMBean(): Server specific implementation of the
     * creation and deployment of the JMX MBean to provide runtime services for my
     * databaseSession.
     *
     * Default is to do nothing. This should be subclassed if required.
     * For platform classes that override the JMXEnabledPlatform - the services MBean
     * is created at platform construction for use during MBean registration here.
     *
     * @see #isRuntimeServicesEnabled()
     * @see #disableRuntimeServices()
     * @see #registerMBean()
     */
    @Override
    public void serverSpecificRegisterMBean() {
        // get and cache module and application name during registration
        MBeanServer mBeanServerRuntime = getMBeanServer();
        ObjectName name = null;
        String sessionName = getMBeanSessionName();
        if (null != sessionName && (shouldRegisterDevelopmentBean || shouldRegisterRuntimeBean)) {
                // Attempt to register new mBean with the server
                if (null != mBeanServerRuntime && shouldRegisterDevelopmentBean) {
                    try {
                        name = new ObjectName(JMX_REGISTRATION_PREFIX + "Development-" + sessionName + ",Type=Configuration");
                    } catch (MalformedObjectNameException mne) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", mne);
                    } catch (Exception exception) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", exception);
                    }

                    // Currently the to be deprecated development MBean is generic to all server platforms
                    MBeanDevelopmentServices developmentMBean = new MBeanDevelopmentServices(getDatabaseSession());
                    ObjectInstance info = null;
                    Object[] args = new Object[2];
                    args[0] = developmentMBean;
                    args[1] = name;
                    try {
                        Method getMethod = PrivilegedAccessHelper.getPublicMethod(MBeanServer.class,
                                "registerMBean", new Class[] {Object.class, ObjectName.class}, false);
                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                            info = (ObjectInstance) AccessController.doPrivileged(new PrivilegedMethodInvoker(getMethod, mBeanServerRuntime, args));
                        } else {
                            info = mBeanServerRuntime.registerMBean(developmentMBean, name);
                        }
                    } catch(InstanceAlreadyExistsException iaee) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", iaee);
                    } catch (MBeanRegistrationException registrationProblem) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", registrationProblem);
                    } catch (Exception e) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", e);
                    }
                    getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "registered_mbean", info, mBeanServerRuntime);
                }

                if (null != mBeanServerRuntime && shouldRegisterRuntimeBean) {
                    try {
                        name = new ObjectName(JMX_REGISTRATION_PREFIX + "Session(" + sessionName + ")");
                    } catch (MalformedObjectNameException mne) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", mne);
                    } catch (Exception exception) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", exception);
                    }

                    ObjectInstance runtimeInstance = null;
                    try {
                        // The cached runtimeServicesMBean is a server platform specific instance
                        Object[] args = new Object[2];
                        args[0] = runtimeServicesMBean;
                        args[1] = name;
                        Method getMethod = PrivilegedAccessHelper.getPublicMethod(MBeanServer.class,
                                "registerMBean", new Class[] {Object.class, ObjectName.class}, false);
                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                           runtimeInstance = (ObjectInstance) AccessController.doPrivileged(new PrivilegedMethodInvoker(getMethod, mBeanServerRuntime, args));
                        } else {
                            runtimeInstance = mBeanServerRuntime.registerMBean(runtimeServicesMBean, name);
                        }
                        setRuntimeServicesMBean(runtimeServicesMBean);
                    } catch(InstanceAlreadyExistsException iaee) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", iaee);
                    } catch (MBeanRegistrationException registrationProblem) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", registrationProblem);
                    } catch (Exception e) {
                        getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_registering_mbean", e);
                    }
                    getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "registered_mbean", runtimeInstance, mBeanServerRuntime);
                }
        }
    }

    /**
     * INTERNAL:
     * serverSpecificUnregisterMBean(): Server specific implementation of the
     * de-registration of the JMX MBean from its server during session logout.
     *
     * @see #isRuntimeServicesEnabled()
     * @see #disableRuntimeServices()
     */
    @Override
    public void serverSpecificUnregisterMBean() {
        MBeanServer mBeanServerRuntime = getMBeanServer();
        ObjectName name = null;
        String sessionName = getMBeanSessionName();
        if (null != sessionName && (shouldRegisterDevelopmentBean || shouldRegisterRuntimeBean)) {
            if(null == mBeanServerRuntime) {
                getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "jmx_unable_to_unregister_mbean", name);
            } else {
                try {
                    // Attempt to register new mBean with the server
                    if (shouldRegisterDevelopmentBean) {
                        try {
                            name = new ObjectName(JMX_REGISTRATION_PREFIX + "Development-" + sessionName + ",Type=Configuration");
                        } catch (MalformedObjectNameException mne) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", mne);
                        } catch (Exception exception) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", exception);
                        }

                        getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "unregistering_mbean", name, mBeanServerRuntime);
                        Object[] args = new Object[1];
                        args[0] = name;
                        try {
                            Method getMethod = PrivilegedAccessHelper.getPublicMethod(MBeanServer.class,
                                    "unregisterMBean", new Class[] {ObjectName.class}, false);
                            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                                AccessController.doPrivileged(new PrivilegedMethodInvoker(getMethod, mBeanServerRuntime, args));
                            } else {
                                mBeanServerRuntime.unregisterMBean(name);
                            }
                            getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "jmx_unregistered_mbean", name, mBeanServerRuntime);
                        } catch(InstanceNotFoundException inf) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", inf);
                        } catch (MBeanRegistrationException mbre) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", mbre);
                        }
                    }

                    if (shouldRegisterRuntimeBean) {
                        try {
                            name = new ObjectName(JMX_REGISTRATION_PREFIX + "Session(" + sessionName + ")");
                        } catch (MalformedObjectNameException mne) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", mne);
                        } catch (Exception exception) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", exception);
                        }

                        getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "unregistering_mbean", name, mBeanServerRuntime);
                        Object[] args = new Object[1];
                        args[0] = name;
                        try {
                            Method getMethod = PrivilegedAccessHelper.getPublicMethod(MBeanServer.class,
                                    "unregisterMBean", new Class[] {ObjectName.class}, false);
                            if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                                AccessController.doPrivileged(new PrivilegedMethodInvoker(getMethod, mBeanServerRuntime, args));
                            } else {
                                mBeanServerRuntime.unregisterMBean(name);
                            }
                            getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "jmx_unregistered_mbean", name, mBeanServerRuntime);
                        } catch(InstanceNotFoundException inf) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", inf);
                        } catch (MBeanRegistrationException registrationProblem) {
                            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", registrationProblem);
                        }
                    }
                } catch (Exception exception) {
                    getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "problem_unregistering_mbean", exception);
                } finally {
                    // de reference the mbean
                    this.setRuntimeServicesMBean(null);
                }
            }
        }
    }

    /**
     * Remove JMX reserved characters from the session name
     */
    protected String getMBeanSessionName() {
        // Check for a valid session - should never occur though
        if(null != getDatabaseSession() && null != getDatabaseSession().getName()) {
            // remove any JMX reserved characters when the session name is file:/drive:/directory
            return getDatabaseSession().getName().replaceAll("[=,:]", "_");
        } else {
            getAbstractSession().log(SessionLog.WARNING, SessionLog.SERVER, "session_key_for_mbean_name_is_null");
            return null;
        }
    }

    /**
     * INTERNAL:
     * Return the cached server specific services MBean
     */
    protected MBeanRuntimeServicesMBean getRuntimeServicesMBean() {
        return runtimeServicesMBean;
    }

    /**
     * INTERNAL:
     * Set the cached server specific services MBean
     */
    protected void setRuntimeServicesMBean(MBeanRuntimeServicesMBean runtimeServicesMBean) {
        this.runtimeServicesMBean = runtimeServicesMBean;
    }

    /**
     * INTERNAL:
     */
    protected String getModuleName(boolean enableDefault) {
        //Object substring = getModuleOrApplicationName();
        if(null == this.moduleName) {
            // Get property from persistence.xml or sessions.xml
            this.moduleName = (String)getDatabaseSession().getProperty(OVERRIDE_JMX_MODULENAME_PROPERTY);
        }
        // if there is no function or property override then answer "unknown" as a default for platforms that do not implement getModuleName()
        if(null == this.moduleName && enableDefault) {
            this.moduleName = DEFAULT_SERVER_NAME_AND_VERSION;
        }
        return this.moduleName;
    }

    /**
     * INTERNAL:
     * 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 JBoss.
     *
     * There are 4 levels of implementation.
     * 1) use the property override jboss.moduleName, or
     * 2) perform a reflective jboss.work.executeThreadRuntime.getModuleName() call, or
     * 3) extract the moduleName:persistence_unit from the server specific classloader string representation, or
     * 3) defer to superclass - usually return "unknown"
     *
     * @return String moduleName
     */
    @Override
    public String getModuleName() {
        return getModuleName(true);
    }

    /**
     * INTERNAL;
     */
    protected void setModuleName(String aName) {
        this.moduleName = aName;
    }

    /**
     * INTERNAL:
     * Lazy initialize the application name by
     * first checking for a persistence.xml property override and then
     * deferring to a default name in the absence of a platform override of this function
     */
    protected String getApplicationName(boolean enableDefault) {
        //Object substring = getModuleOrApplicationName();
        if(null == this.applicationName) {
            // Get property from persistence.xml or sessions.xml
            this.applicationName = (String)getDatabaseSession().getProperty(OVERRIDE_JMX_APPLICATIONNAME_PROPERTY);
        }
        // if there is no function or property override then answer "unknown" as a default for platforms that do not implement getApplicationName()
        if(null == this.applicationName && enableDefault) {
            this.applicationName = DEFAULT_SERVER_NAME_AND_VERSION;
        }
        return this.applicationName;
    }

    /**
     * INTERNAL:
     * 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"
     *
     * There are 4 levels of implementation.
     * 1) use the property override weblogic.applicationName, or
     * 2) perform a reflective weblogic.work.executeThreadRuntime.getApplicationName() call, or
     * 3) extract the moduleName:persistence_unit from the application classloader string representation, or
     * 3) defer to this superclass - usually return "unknown"
     *
     * @return String applicationName
     * @see JMXEnabledPlatform
     */
    public String getApplicationName() {
        return getApplicationName(true);
    }

    /**
     * INTERNAL:
     */
    public void setApplicationName(String aName) {
        this.applicationName = aName;
    }

    /**
     * INTERNAL:
     * Get the applicationName and moduleName from the application server.
     * This function does not use reflective API on the application server, instead it parses
     * the database session name for the module name, and
     * the classLoader (from the Platform.conversionManager) toString() for the application name.
     */
    protected void initializeApplicationNameAndModuleName() {
        // 333160: Fail Fast: we wrap the entire function in a try/catch - even though no exceptions like IOBE should occur - because this initialization should not stop server predeploy in "any" way
        // The database session name is used to get the module name (no reflection required)
        String databaseSessionName = getMBeanSessionName();

        // The classLoader toString() is used to get the application name (no reflection required)
        String classLoaderName = getDatabaseSession().getDatasourcePlatform().getConversionManager().getLoader().toString();
        try {
            getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "jmx_mbean_classloader_in_use",
                "Platform ConversionManager", classLoaderName);
            // Get property from persistence.xml or sessions.xml
            String jpaModuleName = getModuleName(false);
            String jpaApplicationName = getApplicationName(false);

            // Get the name past the matching string if we have a match
            int startIndex = databaseSessionName.indexOf(
                APP_SERVER_CLASSLOADER_MODULE_EJB_SEARCH_STRING_PREFIX);
            if (jpaModuleName == null && startIndex > -1) {
                String subString = databaseSessionName.substring(startIndex +
                    APP_SERVER_CLASSLOADER_MODULE_EJB_SEARCH_STRING_PREFIX.length());
                if(null == subString) {
                    startIndex = databaseSessionName.indexOf(
                        APP_SERVER_CLASSLOADER_MODULE_WAR_SEARCH_STRING_PREFIX);
                    if(startIndex > -1) {
                        subString = databaseSessionName.substring(startIndex +
                                APP_SERVER_CLASSLOADER_MODULE_WAR_SEARCH_STRING_PREFIX.length());
                    }
                }
                // clear terminating characters like ".jar/"
                if(null != subString) {
                    int endIndex = subString.indexOf(APP_SERVER_CLASSLOADER_MODULE_EJB_WAR_SEARCH_STRING_POSTFIX);
                    if(endIndex > -1) {
                        subString = subString.substring(0, endIndex);
                    }
                }
                setModuleName(subString);
            }

            // Get the application name from the ClassLoader, it is also present in the session name
            startIndex = classLoaderName.indexOf(
                APP_SERVER_CLASSLOADER_APPLICATION_PU_SEARCH_STRING_PREFIX);
            if (jpaApplicationName == null && startIndex > -1) {
                jpaApplicationName = classLoaderName.substring(startIndex +
                        APP_SERVER_CLASSLOADER_APPLICATION_PU_SEARCH_STRING_PREFIX.length());
                // Clear terminating delimiting characters like "/}
                if(null != jpaApplicationName) {
                    int endIndex = jpaApplicationName.indexOf(APP_SERVER_CLASSLOADER_APPLICATION_PU_SEARCH_STRING_POSTFIX);
                    if(endIndex > -1) {
                        jpaApplicationName = jpaApplicationName.substring(0, endIndex);
                    }
                }
                // replace encodable characters
                if(null != jpaApplicationName) {
                    jpaApplicationName = jpaApplicationName.replaceAll("[=,:] ", "_");
                }
                setApplicationName(jpaApplicationName);
            }
            // Final check for null values - incorporated into the get functions in these logs (null will be converted to "UNKNOWN")
            getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "mbean_get_application_name",
                getDatabaseSession().getName(), getApplicationName());
            getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "mbean_get_module_name",
                getDatabaseSession().getName(), getModuleName());
        } catch (Exception e) {
            // 333160: Fail Fast: we wrap the entire function in a try/catch - even though no exceptions like IOBE should occur - because this initialization should not stop server predeploy in "any" way
            // However, we should never arrive here
            getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "mbean_get_application_name",
                    classLoaderName, "unavailable");
            getAbstractSession().log(SessionLog.FINEST, SessionLog.SERVER, "mbean_get_module_name",
                    databaseSessionName, "unavailable");
            e.printStackTrace();
        }
    }
}
