Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 32 additions & 9 deletions src/main/java/org/weakref/jmx/AnnotationUtils.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
*/
package org.weakref.jmx;

import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import org.weakref.jmx.JmxException.Reason;

import javax.management.Descriptor;
import javax.management.DescriptorKey;
import javax.management.ImmutableDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
Expand All @@ -27,12 +34,6 @@
import java.util.Set;
import java.util.TreeMap;

import javax.management.Descriptor;
import javax.management.DescriptorKey;
import javax.management.ImmutableDescriptor;

import org.weakref.jmx.JmxException.Reason;

import static java.util.Arrays.asList;

final class AnnotationUtils
Expand Down Expand Up @@ -230,23 +231,45 @@ public static String getDescription(Annotation... annotations)
public static Map<Method, Method> findManagedMethods(Class<?> clazz)
{
Map<Method, Method> result = new HashMap<Method, Method>();
Set<Signature> foundMethods = new HashSet<Signature>();
findManagedMethods(clazz, result, foundMethods);

// gather all publicly available methods
return result;
}

private static void findManagedMethods(Class<?> clazz, Map<Method, Method> result, Set<Signature> foundMethods)
{
// gather all available methods
// this returns everything, even if it's declared in a parent
for (Method method : clazz.getMethods()) {
for (Method method : clazz.getDeclaredMethods()) {
// skip methods that are used internally by the vm for implementing covariance, etc
if (method.isSynthetic() || method.isBridge()) {
continue;
}

Signature methodSignature = new Signature(method);
if (foundMethods.contains(methodSignature)) {
continue;
}
foundMethods.add(methodSignature);

// look for annotations recursively in superclasses or interfaces
Method managedMethod = findManagedMethod(clazz, method.getName(), method.getParameterTypes());
if (managedMethod != null) {
method.setAccessible(true);
managedMethod.setAccessible(true);
result.put(method, managedMethod);
}
}

return result;
Class<?> superclass = clazz.getSuperclass();
if (superclass != null) {
findManagedMethods(superclass, result, foundMethods);
}

for (Class<?> iface : clazz.getInterfaces()) {
findManagedMethods(iface, result, foundMethods);
}
}

public static Method findManagedMethod(Method method)
Expand Down
50 changes: 45 additions & 5 deletions src/main/java/org/weakref/jmx/ReflectionUtils.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
import javax.management.RuntimeOperationsException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import java.util.LinkedHashMap;
import java.util.Collections;

final class ReflectionUtils
{
Expand Down Expand Up @@ -53,8 +53,8 @@ public static Object invoke(Object target, Method method, Object... params)
throws MBeanException, ReflectionException
{
assertNotNull(target, "target");
assertNotNull(target, "method");
assertNotNull(target, "params");
assertNotNull(method, "method");
assertNotNull(params, "params");

try {
Object result = method.invoke(target, params);
Expand Down Expand Up @@ -166,6 +166,46 @@ public static boolean isAssignable(Object value, Class<?> type)
}
}

public static Method getMethod(Class<?> target, String name, Class<?>... parameterTypes)
throws NoSuchMethodException
{
Method method = getMethod0(target, name, parameterTypes);
if (method != null) {
return method;
}

// Throw a NoSuchMethodException
return target.getMethod(name, parameterTypes);
}

private static Method getMethod0(Class<?> target, String name, Class<?>[] parameterTypes)
{
try {
Method method = target.getDeclaredMethod(name, parameterTypes);
method.setAccessible(true);
return method;
}
catch (NoSuchMethodException ignored) {
}

Class<?> superclass = target.getSuperclass();
if (superclass != null) {
Method method = getMethod0(superclass, name, parameterTypes);
if (method != null) {
return method;
}
}

for (Class<?> iface : target.getInterfaces()) {
Method method = getMethod0(iface, name, parameterTypes);
if (method != null) {
return method;
}
}

return null;
}

private static void assertNotNull(Object param, String name)
{
if (param == null) {
Expand Down
54 changes: 29 additions & 25 deletions src/test/java/org/weakref/jmx/AbstractMbeanTest.java
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import static org.weakref.jmx.ReflectionUtils.getMethod;

public abstract class AbstractMbeanTest<T>
{
Expand All @@ -43,8 +44,8 @@ public void testGetterAttributeInfo(String attribute, boolean isIs, Object[] val
String methodName = "set" + attribute;
for (T t : objects) {
String attributeName = toFeatureName(attribute, t);
SimpleObject simpleObject = toSimpleObject(t);
Method setter = simpleObject.getClass().getMethod(methodName, clazz);
SimpleInterface simpleInterface = toSimpleInterface(t);
Method setter = getMethod(simpleInterface.getClass(), methodName, clazz);

MBeanInfo info = getMBeanInfo(t);
MBeanAttributeInfo attributeInfo = getAttributeInfo(info, attributeName);
Expand All @@ -64,8 +65,8 @@ public void testSetterAttributeInfo(String attribute, boolean isIs, Object[] val

for (T t : objects) {
String attributeName = toFeatureName(attribute, t);
SimpleObject simpleObject = toSimpleObject(t);
Method getter = simpleObject.getClass().getMethod(methodName);
SimpleInterface simpleInterface = toSimpleInterface(t);
Method getter = getMethod(simpleInterface.getClass(), methodName);

MBeanInfo info = getMBeanInfo(t);
MBeanAttributeInfo attributeInfo = getAttributeInfo(info, attributeName);
Expand Down Expand Up @@ -165,11 +166,11 @@ public void testGet(String attribute, boolean isIs, Object[] values, Class<?> cl
String methodName = "set" + attribute;
for (T t : objects) {
String attributeName = toFeatureName(attribute, t);
SimpleObject simpleObject = toSimpleObject(t);
Method setter = simpleObject.getClass().getMethod(methodName, clazz);
SimpleInterface simpleInterface = toSimpleInterface(t);
Method setter = getMethod(simpleInterface.getClass(), methodName, clazz);

for (Object value : values) {
setter.invoke(simpleObject, value);
setter.invoke(simpleInterface, value);

assertEquals(getAttribute(t, attributeName), value);
}
Expand All @@ -184,13 +185,13 @@ public void testSet(String attribute, boolean isIs, Object[] values, Class<?> cl

for (T t : objects) {
String attributeName = toFeatureName(attribute, t);
SimpleObject simpleObject = toSimpleObject(t);
Method getter = simpleObject.getClass().getMethod(methodName);
SimpleInterface simpleInterface = toSimpleInterface(t);
Method getter = getMethod(simpleInterface.getClass(), methodName);

for (Object value : values) {
setAttribute(t, attributeName, value);

assertEquals(getter.invoke(simpleObject), value);
assertEquals(getter.invoke(simpleInterface), value);
}
}
}
Expand All @@ -200,9 +201,9 @@ public void testSetFailsOnNotManaged()
throws Exception
{
for (T t : objects) {
SimpleObject simpleObject = toSimpleObject(t);
SimpleInterface simpleInterface = toSimpleInterface(t);

simpleObject.setNotManaged(1);
simpleInterface.setNotManaged(1);
try {
setAttribute(t, "NotManaged", 2);
fail("Should not allow setting unmanaged attribute");
Expand All @@ -211,7 +212,7 @@ public void testSetFailsOnNotManaged()
// ignore
}

assertEquals(simpleObject.getNotManaged(), 1);
assertEquals(simpleInterface.getNotManaged(), 1);
}
}

Expand Down Expand Up @@ -251,8 +252,8 @@ public void testSetFailsOnReadOnly()
throws Exception
{
for (T t : objects) {
SimpleObject simpleObject = toSimpleObject(t);
simpleObject.setReadOnly(1);
SimpleInterface simpleInterface = toSimpleInterface(t);
simpleInterface.setReadOnly(1);
try {
setAttribute(t, "ReadOnly", 2);
fail("Should not allow setting read-only attribute");
Expand All @@ -261,7 +262,7 @@ public void testSetFailsOnReadOnly()
// ignore
}

assertEquals(simpleObject.getReadOnly(), 1);
assertEquals(simpleInterface.getReadOnly(), 1);
}
}

Expand Down Expand Up @@ -339,7 +340,10 @@ Object[][] getFixtures()

new Object[] { "StringValue", false, new Object[] { null, "hello there" }, String.class },

new Object[] { "ObjectValue", false, new Object[] { "random object", 1, true }, Object.class }
new Object[] { "ObjectValue", false, new Object[] { "random object", 1, true }, Object.class },

new Object[] { "PrivateValue", false, new Object[] { Integer.MAX_VALUE, Integer.MIN_VALUE, 0 },
Integer.TYPE },

};
}
Expand All @@ -356,21 +360,21 @@ protected String toFeatureName(String attribute, T t)
return attributeName;
}

protected SimpleObject toSimpleObject(T t)
protected SimpleInterface toSimpleInterface(T t)
{
SimpleObject simpleObject;
if (getObject(t) instanceof SimpleObject) {
simpleObject = (SimpleObject) getObject(t);
SimpleInterface simpleInterface;
if (getObject(t) instanceof SimpleInterface) {
simpleInterface = (SimpleInterface) getObject(t);
}
else if (getObject(t) instanceof FlattenObject) {
simpleObject = ((FlattenObject) getObject(t)).getSimpleObject();
simpleInterface = ((FlattenObject) getObject(t)).getSimpleObject();
}
else if (getObject(t) instanceof NestedObject) {
simpleObject = ((NestedObject) getObject(t)).getSimpleObject();
simpleInterface = ((NestedObject) getObject(t)).getSimpleObject();
}
else {
throw new IllegalArgumentException("Expected objects of type SimpleObject or FlattenObject but got " + getObject(t).getClass().getName());
throw new IllegalArgumentException("Expected objects implementing SimpleInterface or FlattenObject but got " + getObject(t).getClass().getName());
}
return simpleObject;
return simpleInterface;
}
}
Loading