/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
 */
package org.hibernate.jmx.internal;

import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Map;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.hibernate.HibernateException;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Environment;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.jmx.spi.JmxService;
import org.hibernate.service.Service;
import org.hibernate.service.spi.Manageable;
import org.hibernate.service.spi.OptionallyManageable;
import org.hibernate.service.spi.Stoppable;

Standard implementation of JMX services
Author:Steve Ebersole
/** * Standard implementation of JMX services * * @author Steve Ebersole */
public class JmxServiceImpl implements JmxService, Stoppable { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( JmxServiceImpl.class ); public static final String OBJ_NAME_TEMPLATE = "%s:sessionFactory=%s,serviceRole=%s,serviceType=%s"; private final boolean usePlatformServer; private final String agentId; private final String defaultDomain; private final String sessionFactoryName; public JmxServiceImpl(Map configValues) { usePlatformServer = ConfigurationHelper.getBoolean( AvailableSettings.JMX_PLATFORM_SERVER, configValues ); agentId = (String) configValues.get( AvailableSettings.JMX_AGENT_ID ); defaultDomain = (String) configValues.get( AvailableSettings.JMX_DOMAIN_NAME ); sessionFactoryName = ConfigurationHelper.getString( AvailableSettings.JMX_SF_NAME, configValues, ConfigurationHelper.getString( Environment.SESSION_FACTORY_NAME, configValues ) ); } private boolean startedServer; private ArrayList<ObjectName> registeredMBeans; @Override public void stop() { try { // if we either started the JMX server or we registered some MBeans we at least need to look up // MBean server and do *some* work on shutdown. if ( startedServer || registeredMBeans != null ) { MBeanServer mBeanServer = findServer(); if ( mBeanServer == null ) { LOG.unableToLocateMBeanServer(); return; } // release any MBeans we registered if ( registeredMBeans != null ) { for ( ObjectName objectName : registeredMBeans ) { try { LOG.tracev( "Unregistering registered MBean [ON={0}]", objectName ); mBeanServer.unregisterMBean( objectName ); } catch ( Exception e ) { LOG.debugf( "Unable to unregsiter registered MBean [ON=%s] : %s", objectName, e.toString() ); } } } // stop the MBean server if we started it if ( startedServer ) { LOG.trace( "Attempting to release created MBeanServer" ); try { MBeanServerFactory.releaseMBeanServer( mBeanServer ); } catch ( Exception e ) { LOG.unableToReleaseCreatedMBeanServer( e.toString() ); } } } } finally { startedServer = false; if ( registeredMBeans != null ) { registeredMBeans.clear(); registeredMBeans = null; } } } // todo : should serviceRole come first in ObjectName template? depends on the groupings we want in the UI. // as-is mbeans from each sessionFactory are grouped primarily. @Override public void registerService(Manageable service, Class<? extends Service> serviceRole) { if ( OptionallyManageable.class.isInstance( service ) ) { for ( Manageable realManageable : ( (OptionallyManageable) service ).getRealManageables() ) { registerService( realManageable,serviceRole ); } return; } final String domain = service.getManagementDomain() == null ? AvailableSettings.JMX_DEFAULT_OBJ_NAME_DOMAIN : service.getManagementDomain(); final String serviceType = service.getManagementServiceType() == null ? service.getClass().getName() : service.getManagementServiceType(); try { final ObjectName objectName = new ObjectName( String.format( OBJ_NAME_TEMPLATE, domain, sessionFactoryName, serviceRole.getName(), serviceType ) ); registerMBean( objectName, service.getManagementBean() ); } catch ( MalformedObjectNameException e ) { throw new HibernateException( "Unable to generate service IbjectName", e ); } } @Override public void registerMBean(ObjectName objectName, Object mBean) { MBeanServer mBeanServer = findServer(); if ( mBeanServer == null ) { if ( startedServer ) { throw new HibernateException( "Could not locate previously started MBeanServer" ); } mBeanServer = startMBeanServer(); startedServer = true; } try { mBeanServer.registerMBean( mBean, objectName ); if ( registeredMBeans == null ) { registeredMBeans = new ArrayList<ObjectName>(); } registeredMBeans.add( objectName ); } catch ( Exception e ) { throw new HibernateException( "Unable to register MBean [ON=" + objectName + "]", e ); } }
Locate the MBean server to use based on user input from startup.
Returns:The MBean server to use.
/** * Locate the MBean server to use based on user input from startup. * * @return The MBean server to use. */
private MBeanServer findServer() { if ( usePlatformServer ) { // they specified to use the platform (vm) server return ManagementFactory.getPlatformMBeanServer(); } // otherwise lookup all servers by (optional) agentId. // IMPL NOTE : the findMBeanServer call treats a null agentId to mean match all... ArrayList<MBeanServer> mbeanServers = MBeanServerFactory.findMBeanServer( agentId ); if ( defaultDomain == null ) { // they did not specify a domain by which to locate a particular MBeanServer to use, so chose the first return mbeanServers.get( 0 ); } for ( MBeanServer mbeanServer : mbeanServers ) { // they did specify a domain, so attempt to locate an MBeanServer with a matching default domain, returning it // if we find it. if ( defaultDomain.equals( mbeanServer.getDefaultDomain() ) ) { return mbeanServer; } } return null; } private MBeanServer startMBeanServer() { try { return MBeanServerFactory.createMBeanServer( defaultDomain ); } catch ( Exception e ) { throw new HibernateException( "Unable to start MBeanServer", e ); } } }