/******************************************************************************* * Copyright (c) 2010, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * 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. ******************************************************************************/ 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. */ public 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() { 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.WARNING, 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.WARNING, 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() */ 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() */ 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 * @return */ 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 * @param runtimeServicesMBean */ protected void setRuntimeServicesMBean(MBeanRuntimeServicesMBean runtimeServicesMBean) { this.runtimeServicesMBean = runtimeServicesMBean; } /** * INTERNAL: * @param enableDefault * @return */ 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; * @param aName */ 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 * @param enableDefault * @return */ 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: * @param aName */ 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(); } } }