package org.radargun.service;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.radargun.logging.Log;
import org.radargun.logging.LogFactory;
/**
* Extracts configuration to properties. Valid for caches since 5.2
*
* @author Michal Linhard <mlinhard@redhat.com>
*
*/
public class ConfigDumpHelper {
protected static Log log = LogFactory.getLog(ConfigDumpHelper.class);
private static Method plainToString = null;
static {
try {
plainToString = Object.class.getMethod("toString");
} catch (Exception e) {
log.error("Error while initializing", e);
}
}
public Properties dumpGlobal(GlobalConfiguration globalConfiguration, String jmxDomain, String managerName) {
Properties properties = new Properties();
try {
reflect(globalConfiguration, properties, null);
} catch (Exception e) {
log.error("Error while dumping global config as properties", e);
}
return properties;
}
public Properties dumpCache(Configuration configuration, String domain, String managerName, String cacheName) {
Properties properties = new Properties();
try {
reflect(configuration, properties, null);
} catch (Exception e) {
log.error("Error while dumping " + cacheName + " cache config as properties", e);
}
return properties;
}
public Properties dumpJGroups(String jmxDomain, String clusterName) {
Properties properties = new Properties();
try {
MBeanServer mbeanServer = ManagementFactory.getPlatformMBeanServer();
Set<ObjectInstance> beanObjs = mbeanServer.queryMBeans(new ObjectName(String.format("%s:type=protocol,cluster=\"%s\",protocol=*", jmxDomain, clusterName)), null);
if (beanObjs.isEmpty()) {
log.error("no JGroups protocols found");
return properties;
}
for (ObjectInstance beanObj : beanObjs) {
ObjectName protocolObjectName = beanObj.getObjectName();
MBeanInfo protocolBean = mbeanServer.getMBeanInfo(protocolObjectName);
String protocolName = protocolObjectName.getKeyProperty("protocol");
for (MBeanAttributeInfo info : protocolBean.getAttributes()) {
String propName = info.getName();
Object propValue = mbeanServer.getAttribute(protocolObjectName, propName);
properties.setProperty(protocolName + "." + propName, propValue == null ? "null" : propValue.toString());
}
}
} catch (Exception e) {
log.error("Error while dumping JGroups config as properties", e);
}
return properties;
}
private List<Method> getMethods(Class<?> clazz) {
Class<?> c = clazz;
List<Method> r = new ArrayList<Method>();
while (c != null && c != Object.class) {
for (Method m : c.getDeclaredMethods()) {
r.add(m);
}
c = c.getSuperclass();
}
return r;
}
private boolean hasPlainToString(Class<?> cls, Object obj) {
try {
if (cls.getMethod("toString") == plainToString) {
return true;
}
String plainToStringValue = cls.getName() + "@" + Integer.toHexString(System.identityHashCode(obj));
return plainToStringValue.equals(obj.toString());
} catch (Exception e) {
return false;
}
}
/**
*
* This is a generic method for reflection copied from PropertyFormatter from Infinispan 6.0
*
* @param obj
* @param p
* @param prefix
*/
private void reflect(Object obj, Properties p, String prefix) {
try {
if (obj == null) {
p.put(prefix, "null");
return;
}
Class<?> cls = obj.getClass();
if (cls.getName().startsWith("org.infinispan.config") && !cls.isEnum()) {
for (Method m : getMethods(obj.getClass())) {
if (m.getParameterTypes().length != 0 || "toString".equals(m.getName()) || "hashCode".equals(m.getName()) || "toProperties".equals(m.getName())) {
continue;
}
try {
String prefixDot = prefix == null || "".equals(prefix) ? "" : prefix + ".";
reflect(m.invoke(obj), p, prefixDot + m.getName());
} catch (IllegalAccessException e) {
// ok
}
}
} else if (Collection.class.isAssignableFrom(cls)) {
Collection<?> collection = (Collection<?>) obj;
Iterator<?> iter = collection.iterator();
for (int i = 0; i < collection.size(); i++) {
reflect(iter.next(), p, prefix + "[" + i + "]");
}
} else if (cls.isArray()) {
Object[] a = (Object[]) obj;
for (int i = 0; i < a.length; i++) {
reflect(a[i], p, prefix + "[" + i + "]");
}
} else if (hasPlainToString(cls, obj)) {
// we have a class that doesn't have a nice toString implementation
p.put(prefix, cls.getName());
} else {
// we have a single value
p.put(prefix, obj.toString());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}