/*
* RHQ Management Platform
* Copyright (C) 2005-2008 Red Hat, Inc.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2, as
* published by the Free Software Foundation, and/or the GNU Lesser
* General Public License, version 2.1, also as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with this program;
* if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.rhq.core.pluginapi.util;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.HashSet;
import java.util.Set;
import java.lang.reflect.Method;
import javax.management.openmbean.CompositeData;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jetbrains.annotations.Nullable;
import org.rhq.core.domain.measurement.MeasurementScheduleRequest;
import org.rhq.core.util.exception.ThrowableUtil;
/**
* @author Greg Hinkle
*/
public class ObjectUtil {
private static final Log LOG = LogFactory.getLog(ObjectUtil.class);
/**
* Returns the value of the property with the specified name for the given Object, or null if the Object has no such
* property.
*
* @param obj an Object
* @param propertyName the name of the property whose value should be returned
*
* @return the value of the property with the specified name for the given Object, or null if the Object has no such
* property
*/
@Nullable
public static Object lookupAttributeProperty(Object obj, String propertyName) {
Object value = null;
if (obj instanceof CompositeData) {
CompositeData compositeData = ((CompositeData)obj);
if (compositeData.containsKey(propertyName)) {
value = compositeData.get(propertyName);
} else {
LOG.debug("Unable to read attribute/property [" + propertyName + "] from object [" + obj + "] using OpenMBean API - no such property.");
}
} else {
// Try to use reflection.
try {
PropertyDescriptor[] pds = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
boolean propertyFound = false;
for (PropertyDescriptor pd : pds) {
if (pd.getName().equals(propertyName)) {
propertyFound = true;
Method readMethod = pd.getReadMethod();
if (readMethod == null) {
LOG.debug("Unable to read attribute/property [" + propertyName + "] from object [" + obj
+ "] using Reflection - property is not readable (i.e. it has no getter).");
} else {
value = readMethod.invoke(obj);
}
}
}
if (!propertyFound) {
LOG.debug("Unable to read attribute/property [" + propertyName + "] from object [" + obj
+ "] using Reflection - no such property.");
}
} catch (Exception e) {
LOG.debug("Unable to read attribute/property [" + propertyName + "] from object [" + obj
+ "] using Reflection - cause: " + ThrowableUtil.getAllMessages(e));
}
}
return value;
}
private static Set<String> getAttributeNames(Set<MeasurementScheduleRequest> requests) {
Set<String> names = new HashSet<String>();
for (MeasurementScheduleRequest request : requests) {
names.add(getAttributeName(request.getName()));
}
return names;
}
private static String getAttributeName(String property) {
if (property.startsWith("{")) {
return property.substring(1, property.indexOf('.'));
} else {
return property;
}
}
private static String getAttributeProperty(String property) {
if (property.startsWith("{")) {
return property.substring(property.indexOf('.') + 1, property.length() - 1);
} else {
return null;
}
}
/**
* Reads a numeric value from a deep object graph as per {@see ObjectUtil.lookupDeepAttributeProperty()}
*
* @param value The object to look into
* @param propertyPath the property path to search
*
* @return the double value read from the object's property path or Double.NaN if it can't be read
*/
public static Double lookupDeepNumericAttributeProperty(Object value, String propertyPath) {
Object val = lookupDeepAttributeProperty(value, propertyPath);
if (val instanceof Number) {
return ((Number) val).doubleValue();
} else {
return Double.NaN;
}
}
/**
* Looks up deep object graph attributes using a dot delimited java bean spec style path. So if I have an object A
* with a Member object B with a String value C I can refer to it as "b.c" and pass in the object A and I'll get
* back the value of a.getB().getC()
*
* @param value The object to look into
* @param propertyPath the property path to search
*
* @return the value read from the object's property path
*/
public static Object lookupDeepAttributeProperty(Object value, String propertyPath) {
if (value==null)
return null;
String[] ps = propertyPath.split("\\.", 2);
String searchProperty = ps[0];
if (value instanceof CompositeData) {
CompositeData compositeData = ((CompositeData) value);
if (compositeData.containsKey(searchProperty)) {
value = compositeData.get(searchProperty);
} else {
LOG.debug("Unable to read attribute property [" + propertyPath + "] from composite data value");
}
} else {
// Try to use reflection
try {
PropertyDescriptor[] pds = Introspector.getBeanInfo(value.getClass()).getPropertyDescriptors();
for (PropertyDescriptor pd : pds) {
if (pd.getName().equals(searchProperty)) {
value = pd.getReadMethod().invoke(value);
}
}
} catch (Exception e) {
LOG.debug("Unable to read property from measurement attribute [" + searchProperty + "] not found on ["
+ ((value != null) ? value.getClass().getSimpleName() : "null") + "]");
}
}
if (ps.length > 1) {
value = lookupDeepAttributeProperty(value, ps[1]);
}
return value;
}
// Prevent instantiation of this class.
private ObjectUtil() {
}
}