/*
* Copyright 2012 dominictootell
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.greencheek.processio.service.persistence.jmx;
import org.greencheek.processio.domain.CurrentProcessIO;
import org.greencheek.processio.domain.jmx.ProcessIOUsageHolder;
import org.greencheek.processio.service.usage.ProcessIOUsage;
import org.greencheek.processio.service.persistence.ProcessIOUsagePersistence;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.management.*;
import java.lang.management.ManagementFactory;
/**
* Persists a {@link ProcessIOUsageHolder} object in the JMXServer. This holder object holds onto a {@link org.greencheek.processio.domain.ProcessIO}
* object that stores the current and previous io read and written by the process. The {@link ProcessIOUsageHolder} object
* is a JMX MXBean
* <p>
* User: dominictootell
* Date: 22/04/2012
* Time: 16:38
* </p>
*/
public class ProcessIOUsagePersistenceViaJmx implements ProcessIOUsagePersistence {
private static final Logger log = LoggerFactory.getLogger(ProcessIOUsagePersistenceViaJmx.class);
private final ProcessIOUsageHolder ioUsageHolder;
public static final String DEFAULT_JMX_DOMAIN_NAME="org.greencheek";
public static final String DEFAULT_JMX_BEAN_NAME="processiousage";
public static final String DEFAULT_COMPOSED_JMX_BEAN_NAME = DEFAULT_JMX_DOMAIN_NAME + ":type=" + DEFAULT_JMX_BEAN_NAME;
public static final ObjectName DEFAULT_JMX_OBJECT_NAME;
static {
ObjectName o = null;
try {
o = new ObjectName(DEFAULT_JMX_DOMAIN_NAME + ":type=" + DEFAULT_JMX_BEAN_NAME);
} catch(MalformedObjectNameException e) {
// won't happen. The default is safe.
}
DEFAULT_JMX_OBJECT_NAME = o;
}
private static final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
private final String beanObjectNameStringRepresentation;
private final boolean registeredInJmx;
private final ObjectName jmxRegisteredObjectName;
/**
* Persist/Register the given ProcessIOUsage object with the jvm's MBeanServer
*
* @param ioUsage The {@link ProcessIOUsageHolder} object to persist in the Jvm MBean Server
*/
public ProcessIOUsagePersistenceViaJmx(ProcessIOUsage ioUsage) {
this(ioUsage,DEFAULT_JMX_OBJECT_NAME,DEFAULT_COMPOSED_JMX_BEAN_NAME);
}
/**
* Persist/Register the given ProcessIOUsage object with the jvm's MBeanServer
*
* @param ioUsage The io object to persist
* @param jmxObjectName the jmx name to persist the ProcessIOUsage object under
* @param beanObjectName the jmx domain under which to register the {@link ProcessIOUsageHolder} object
*/
public ProcessIOUsagePersistenceViaJmx(ProcessIOUsage ioUsage, ObjectName jmxObjectName,
String beanObjectName) {
ioUsageHolder = new ProcessIOUsageHolder(ioUsage);
if (jmxObjectName == null) {
log.error("Using Default ObjectName to register bean, the given object name ({}) could not be used. Registering under {}", beanObjectName, DEFAULT_COMPOSED_JMX_BEAN_NAME);
jmxObjectName = DEFAULT_JMX_OBJECT_NAME;
beanObjectNameStringRepresentation = DEFAULT_COMPOSED_JMX_BEAN_NAME;
} else {
this.beanObjectNameStringRepresentation = beanObjectName;
}
boolean registered = false;
try {
server.registerMBean(ioUsageHolder, jmxObjectName);
registered = true;
} catch (NullPointerException e) {
log.warn("Unable to register with jmx, invalid bean name:{}", beanObjectName, e);
} catch (InstanceAlreadyExistsException e) {
log.warn("Unable to register with jmx, bean already exists:{}", beanObjectName, e);
} catch (MBeanRegistrationException e) {
log.warn("Unable to register with jmx, exception during registration:{}", beanObjectName, e);
} catch (NotCompliantMBeanException e) {
log.warn("Unable to register with jmx, bean is not compatible:{}", beanObjectName, e);
} finally {
registeredInJmx = registered;
jmxRegisteredObjectName = jmxObjectName;
}
}
public ProcessIOUsagePersistenceViaJmx(ProcessIOUsage ioUsage,
String jmxDomainName, String beanName) {
this(ioUsage,createObjectName(jmxDomainName,beanName),jmxDomainName+":type="+beanName);
}
private static ObjectName createObjectName(String jmxDomainName,String beanName) {
String beanObjectName = jmxDomainName+":type="+beanName;
ObjectName objName = null;
try {
objName = new ObjectName(beanObjectName);
} catch (MalformedObjectNameException e) {
log.warn("Unable to register with jmx, invalid bean name:{}", beanObjectName, e);
}
return objName;
}
public boolean isRegisteredInJmx() {
return registeredInJmx;
}
@Override
public void init() {
}
/**
* If the bean was registered in the constructor, then an attempt will be made to remove the bean from
* the jmx server on shutdown
*/
@Override
public void destroy() {
if(isRegisteredInJmx()) {
try {
server.unregisterMBean(getBeanObjectName());
} catch (MBeanRegistrationException e) {
log.warn("Unable to unregister object with jmx:{}", beanObjectNameStringRepresentation, e);
} catch (InstanceNotFoundException e) {
log.warn("Unable to unregister object with jmx, object not registered:{}", beanObjectNameStringRepresentation, e);
}
}
}
@Override
public void persist(CurrentProcessIO io) {
ioUsageHolder.setProcessIO(io);
}
public ObjectName getBeanObjectName() {
return jmxRegisteredObjectName;
}
}