/*
 * 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 = AccessController.doPrivileged(
                            new PrivilegedExceptionAction<List<MBeanServer>>() {
                                @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 {
                        @SuppressWarnings({"rawtypes"})
                        Method getMethod = PrivilegedAccessHelper.getPublicMethod(MBeanServer.class,
                                "registerMBean", new Class[] {Object.class, ObjectName.class}, false);
                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                            info = AccessController.doPrivileged(new PrivilegedMethodInvoker<ObjectInstance>(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;
                        @SuppressWarnings({"rawtypes"})
                        Method getMethod = PrivilegedAccessHelper.getPublicMethod(MBeanServer.class,
                                "registerMBean", new Class[] {Object.class, ObjectName.class}, false);
                        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                           runtimeInstance = AccessController.doPrivileged(new PrivilegedMethodInvoker<ObjectInstance>(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 {
                            @SuppressWarnings({"rawtypes"})
                            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 {
                            @SuppressWarnings({"rawtypes"})
                            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();
        }
    }
}
