[infinispan-commits] Infinispan SVN: r800 - in trunk/core/src: test/java/org/infinispan/jmx and 1 other directory.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Sep 9 06:50:50 EDT 2009
Author: galder.zamarreno at jboss.com
Date: 2009-09-09 06:50:49 -0400 (Wed, 09 Sep 2009)
New Revision: 800
Modified:
trunk/core/src/main/java/org/infinispan/jmx/ResourceDMBean.java
trunk/core/src/test/java/org/infinispan/jmx/CacheManagerMBeanTest.java
Log:
[ISPN-189] (ResourceDMBean.invoke() should check if method invoked is a managed operation) Fixed by checking whether the invoker operation is contained in the mbean operation list.
Modified: trunk/core/src/main/java/org/infinispan/jmx/ResourceDMBean.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/jmx/ResourceDMBean.java 2009-09-09 10:41:41 UTC (rev 799)
+++ trunk/core/src/main/java/org/infinispan/jmx/ResourceDMBean.java 2009-09-09 10:50:49 UTC (rev 800)
@@ -37,6 +37,8 @@
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.ReflectionException;
+import javax.management.ServiceNotFoundException;
+
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
@@ -48,22 +50,22 @@
import java.util.regex.Pattern;
/**
- * This class was entirely copied from jgroups 2.7 (same name there). Couldn't simply reuse it because jgroups does not
- * ship with MBean, ManagedAttribute and ManagedOperation. Once jgroups will ship these classes, the code can be
- * dinalmically reused from there.
- *
+ * This class was entirely copied from jgroups 2.7 (same name there). Couldn't simply reuse it
+ * because jgroups does not ship with MBean, ManagedAttribute and ManagedOperation. Once jgroups
+ * will ship these classes, the code can be dinalmically reused from there.
+ *
+ * The original JGroup's ResourceDMBean logic has been modified so that {@link #invoke()} method checks
+ * whether the operation called has been exposed as a {@link ManagedOperation}, otherwise the call
+ * fails. JGroups deviated from this logic on purpouse because they liked the fact that you could expose
+ * all class methods by simply annotating class with {@link MBean} annotation.
+ *
* @author Mircea.Markus at jboss.com
+ * @author Galder Zamarreño
* @since 4.0
*/
public class ResourceDMBean implements DynamicMBean {
- private static final Class<?>[] primitives = {int.class,
- byte.class,
- short.class,
- long.class,
- float.class,
- double.class,
- boolean.class,
- char.class};
+ private static final Class<?>[] primitives = { int.class, byte.class, short.class, long.class,
+ float.class, double.class, boolean.class, char.class };
private static final String MBEAN_DESCRITION = "Dynamic MBean Description";
@@ -72,7 +74,7 @@
private String description = "";
private final MBeanAttributeInfo[] attrInfo;
- private final MBeanOperationInfo[] opInfo;
+ private final MBeanOperationInfo[] opInfos;
private final HashMap<String, AttributeEntry> atts = new HashMap<String, AttributeEntry>();
private final List<MBeanOperationInfo> ops = new ArrayList<MBeanOperationInfo>();
@@ -95,26 +97,18 @@
info = entry.getInfo();
attrInfo[i++] = info;
if (log.isInfoEnabled()) {
- log.trace("Attribute " + info.getName()
- + "[r="
- + info.isReadable()
- + ",w="
- + info.isWritable()
- + ",is="
- + info.isIs()
- + ",type="
- + info.getType()
- + "]");
+ log.trace("Attribute " + info.getName() + "[r=" + info.isReadable() + ",w="
+ + info.isWritable() + ",is=" + info.isIs() + ",type=" + info.getType() + "]");
}
}
- opInfo = new MBeanOperationInfo[ops.size()];
- ops.toArray(opInfo);
+ opInfos = new MBeanOperationInfo[ops.size()];
+ ops.toArray(opInfos);
- if (log.isInfoEnabled()) {
+ if (log.isTraceEnabled()) {
if (ops.size() > 0)
log.trace("Operations are:");
- for (MBeanOperationInfo op : opInfo) {
+ for (MBeanOperationInfo op : opInfos) {
log.trace("Operation " + op.getReturnType() + " " + op.getName());
}
}
@@ -131,18 +125,13 @@
if (log.isDebugEnabled()) {
log.debug("@MBean description set - " + mbean.description());
}
- MBeanAttributeInfo info = new MBeanAttributeInfo(MBEAN_DESCRITION,
- "java.lang.String",
- "@MBean description",
- true,
- false,
- false);
+ MBeanAttributeInfo info = new MBeanAttributeInfo(MBEAN_DESCRITION, "java.lang.String",
+ "@MBean description", true, false, false);
try {
- atts.put(MBEAN_DESCRITION,
- new FieldAttributeEntry(info, getClass().getDeclaredField("description")));
- }
- catch (NoSuchFieldException e) {
- //this should not happen unless somebody removes description field
+ atts.put(MBEAN_DESCRITION, new FieldAttributeEntry(info, getClass().getDeclaredField(
+ "description")));
+ } catch (NoSuchFieldException e) {
+ // this should not happen unless somebody removes description field
log.warn("Could not reflect field description of this class. Was it removed?");
}
}
@@ -150,12 +139,8 @@
public synchronized MBeanInfo getMBeanInfo() {
- return new MBeanInfo(getObject().getClass().getCanonicalName(),
- description,
- attrInfo,
- null,
- opInfo,
- null);
+ return new MBeanInfo(getObject().getClass().getCanonicalName(), description, attrInfo, null,
+ opInfos, null);
}
public synchronized Object getAttribute(String name) throws AttributeNotFoundException {
@@ -164,7 +149,8 @@
Attribute attr = getNamedAttribute(name);
if (attr == null) {
- throw new AttributeNotFoundException("Unknown attribute '" + name + "'. Known attributes names are: " + atts.keySet());
+ throw new AttributeNotFoundException("Unknown attribute '" + name
+ + "'. Known attributes names are: " + atts.keySet());
}
return attr.getValue();
}
@@ -198,9 +184,8 @@
results.add(attr);
} else {
if (log.isWarnEnabled()) {
- log.warn("Failed to update attribute name " + attr.getName()
- + " with value "
- + attr.getValue());
+ log.warn("Failed to update attribute name " + attr.getName() + " with value "
+ + attr.getValue());
}
}
}
@@ -208,19 +193,32 @@
}
public Object invoke(String name, Object[] args, String[] sig) throws MBeanException,
- ReflectionException {
- try {
- if (log.isDebugEnabled()) {
- log.debug("Invoke method called on " + name);
+ ReflectionException {
+ if (log.isDebugEnabled()) {
+ log.debug("Invoke method called on " + name);
+ }
+
+ MBeanOperationInfo opInfo = null;
+ for (MBeanOperationInfo op : opInfos) {
+ if (op.getName().equals(name)) {
+ opInfo = op;
+ break;
}
+ }
+
+ if (opInfo == null) {
+ final String msg = "Operation " + name + " not in ModelMBeanInfo";
+ throw new MBeanException(new ServiceNotFoundException(msg), msg);
+ }
+
+ try {
Class<?>[] classes = new Class[sig.length];
for (int i = 0; i < classes.length; i++) {
classes[i] = getClassForName(sig[i]);
}
Method method = getObject().getClass().getMethod(name, classes);
return method.invoke(getObject(), args);
- }
- catch (Exception e) {
+ } catch (Exception e) {
throw new MBeanException(e);
}
}
@@ -229,9 +227,8 @@
try {
Class<?> c = Util.loadClass(name);
return c;
- }
- catch (ClassNotFoundException cnfe) {
- //Could be a primitive - let's check
+ } catch (ClassNotFoundException cnfe) {
+ // Could be a primitive - let's check
for (int i = 0; i < primitives.length; i++) {
if (name.equals(primitives[i].getName())) {
return primitives[i];
@@ -242,116 +239,103 @@
}
private void findMethods() {
- //find all methods but don't include methods from Object class
- List<Method> methods = new ArrayList<Method>(Arrays.asList(getObject().getClass().getMethods()));
+ // find all methods but don't include methods from Object class
+ List<Method> methods = new ArrayList<Method>(Arrays.asList(getObject().getClass()
+ .getMethods()));
List<Method> objectMethods = new ArrayList<Method>(Arrays.asList(Object.class.getMethods()));
methods.removeAll(objectMethods);
for (Method method : methods) {
- //does method have @ManagedAttribute annotation?
+ // does method have @ManagedAttribute annotation?
ManagedAttribute attr = method.getAnnotation(ManagedAttribute.class);
if (attr != null) {
String methodName = method.getName();
if (!methodName.startsWith("get") && !methodName.startsWith("set")
- && !methodName.startsWith("is")) {
+ && !methodName.startsWith("is")) {
if (log.isWarnEnabled())
log.warn("method name " + methodName
- + " doesn't start with \"get\", \"set\", or \"is\""
- + ", but is annotated with @ManagedAttribute: will be ignored");
+ + " doesn't start with \"get\", \"set\", or \"is\""
+ + ", but is annotated with @ManagedAttribute: will be ignored");
} else {
MBeanAttributeInfo info = null;
- //Is name field of @ManagedAttributed used?
+ // Is name field of @ManagedAttributed used?
String attributeName = attr.name().length() > 0 ? attr.name().trim() : null;
boolean writeAttribute = false;
if (isSetMethod(method)) { // setter
attributeName = (attributeName == null) ? methodName.substring(3) : attributeName;
- info = new MBeanAttributeInfo(attributeName,
- method.getParameterTypes()[0].getCanonicalName(),
- attr.description(),
- true,
- true,
- false);
+ info = new MBeanAttributeInfo(attributeName, method.getParameterTypes()[0]
+ .getCanonicalName(), attr.description(), true, true, false);
writeAttribute = true;
} else { // getter
- if (method.getParameterTypes().length == 0 && method.getReturnType() != java.lang.Void.TYPE) {
+ if (method.getParameterTypes().length == 0
+ && method.getReturnType() != java.lang.Void.TYPE) {
boolean hasSetter = atts.containsKey(attributeName);
- //we found is method
+ // we found is method
if (methodName.startsWith("is")) {
- attributeName = (attributeName == null) ? methodName.substring(2) : attributeName;
- info = new MBeanAttributeInfo(attributeName,
- method.getReturnType().getCanonicalName(),
- attr.description(),
- true,
- hasSetter,
- true);
+ attributeName = (attributeName == null) ? methodName.substring(2)
+ : attributeName;
+ info = new MBeanAttributeInfo(attributeName, method.getReturnType()
+ .getCanonicalName(), attr.description(), true, hasSetter, true);
} else {
- //this has to be get
- attributeName = (attributeName == null) ? methodName.substring(3) : attributeName;
- info = new MBeanAttributeInfo(attributeName,
- method.getReturnType().getCanonicalName(),
- attr.description(),
- true,
- hasSetter,
- false);
+ // this has to be get
+ attributeName = (attributeName == null) ? methodName.substring(3)
+ : attributeName;
+ info = new MBeanAttributeInfo(attributeName, method.getReturnType()
+ .getCanonicalName(), attr.description(), true, hasSetter, false);
}
} else {
if (log.isWarnEnabled()) {
log.warn("Method " + method.getName()
- + " must have a valid return type and zero parameters");
+ + " must have a valid return type and zero parameters");
}
continue;
}
}
AttributeEntry ae = atts.get(attributeName);
- //is it a read method?
+ // is it a read method?
if (!writeAttribute) {
- //we already have annotated field as read
+ // we already have annotated field as read
if (ae instanceof FieldAttributeEntry && ae.getInfo().isReadable()) {
log.warn("not adding annotated method " + method
- + " since we already have read attribute");
+ + " since we already have read attribute");
}
- //we already have annotated set method
+ // we already have annotated set method
else if (ae instanceof MethodAttributeEntry) {
MethodAttributeEntry mae = (MethodAttributeEntry) ae;
if (mae.hasSetMethod()) {
- atts.put(attributeName,
- new MethodAttributeEntry(mae.getInfo(), mae.getSetMethod(), method));
+ atts.put(attributeName, new MethodAttributeEntry(mae.getInfo(), mae
+ .getSetMethod(), method));
}
- } //we don't have such entry
+ } // we don't have such entry
else {
atts.put(attributeName, new MethodAttributeEntry(info, null, method));
}
- }//is it a set method?
+ }// is it a set method?
else {
if (ae instanceof FieldAttributeEntry) {
- //we already have annotated field as write
+ // we already have annotated field as write
if (ae.getInfo().isWritable()) {
log.warn("Not adding annotated method " + methodName
- + " since we already have writable attribute");
+ + " since we already have writable attribute");
} else {
- //we already have annotated field as read
- //lets make the field writable
+ // we already have annotated field as read
+ // lets make the field writable
Field f = ((FieldAttributeEntry) ae).getField();
- MBeanAttributeInfo i = new MBeanAttributeInfo(ae.getInfo().getName(),
- f.getType().getCanonicalName(),
- attr.description(),
- true,
- Modifier.isFinal(f.getModifiers()) ? false : true,
- false);
+ MBeanAttributeInfo i = new MBeanAttributeInfo(ae.getInfo().getName(), f
+ .getType().getCanonicalName(), attr.description(), true, Modifier
+ .isFinal(f.getModifiers()) ? false : true, false);
atts.put(attributeName, new FieldAttributeEntry(i, f));
}
}
- //we already have annotated getOrIs method
+ // we already have annotated getOrIs method
else if (ae instanceof MethodAttributeEntry) {
MethodAttributeEntry mae = (MethodAttributeEntry) ae;
if (mae.hasIsOrGetMethod()) {
- atts.put(attributeName,
- new MethodAttributeEntry(info,
- method,
- mae.getIsOrGetMethod()));
+ atts.put(attributeName, new MethodAttributeEntry(info, method, mae
+ .getIsOrGetMethod()));
}
- } //we don't have such entry
+ } // we don't have such entry
else {
atts.put(attributeName, new MethodAttributeEntry(info, method, null));
}
@@ -365,7 +349,7 @@
} else if (isIsMethod(method)) {
attName = attName.substring(2);
}
- //expose unless we already exposed matching attribute field
+ // expose unless we already exposed matching attribute field
boolean isAlreadyExposed = atts.containsKey(attName);
if (!isAlreadyExposed) {
ops.add(new MBeanOperationInfo(op != null ? op.description() : "", method));
@@ -375,25 +359,24 @@
}
private boolean isSetMethod(Method method) {
- return (method.getName().startsWith("set") &&
- method.getParameterTypes().length == 1 &&
- method.getReturnType() == java.lang.Void.TYPE);
+ return (method.getName().startsWith("set") && method.getParameterTypes().length == 1 && method
+ .getReturnType() == java.lang.Void.TYPE);
}
private boolean isGetMethod(Method method) {
- return (method.getParameterTypes().length == 0 &&
- method.getReturnType() != java.lang.Void.TYPE &&
- method.getName().startsWith("get"));
+ return (method.getParameterTypes().length == 0
+ && method.getReturnType() != java.lang.Void.TYPE && method.getName().startsWith(
+ "get"));
}
private boolean isIsMethod(Method method) {
- return (method.getParameterTypes().length == 0 &&
- (method.getReturnType() == boolean.class || method.getReturnType() == Boolean.class) &&
- method.getName().startsWith("is"));
+ return (method.getParameterTypes().length == 0
+ && (method.getReturnType() == boolean.class || method.getReturnType() == Boolean.class) && method
+ .getName().startsWith("is"));
}
private void findFields() {
- //traverse class hierarchy and find all annotated fields
+ // traverse class hierarchy and find all annotated fields
for (Class<?> clazz = getObject().getClass(); clazz != null; clazz = clazz.getSuperclass()) {
Field[] fields = clazz.getDeclaredFields();
@@ -401,12 +384,9 @@
ManagedAttribute attr = field.getAnnotation(ManagedAttribute.class);
if (attr != null) {
String fieldName = renameToJavaCodingConvention(field.getName());
- MBeanAttributeInfo info = new MBeanAttributeInfo(fieldName,
- field.getType().getCanonicalName(),
- attr.description(),
- true,
- Modifier.isFinal(field.getModifiers()) ? false : attr.writable(),
- false);
+ MBeanAttributeInfo info = new MBeanAttributeInfo(fieldName, field.getType()
+ .getCanonicalName(), attr.description(), true, Modifier.isFinal(field
+ .getModifiers()) ? false : attr.writable(), false);
atts.put(fieldName, new FieldAttributeEntry(info, field));
}
@@ -425,17 +405,11 @@
try {
result = new Attribute(name, entry.invoke(null));
if (log.isDebugEnabled())
- log.debug("Attribute " + name
- + " has r="
- + i.isReadable()
- + ",w="
- + i.isWritable()
- + ",is="
- + i.isIs()
- + " and value "
- + result.getValue());
- }
- catch (Exception e) {
+ log
+ .debug("Attribute " + name + " has r=" + i.isReadable() + ",w="
+ + i.isWritable() + ",is=" + i.isIs() + " and value "
+ + result.getValue());
+ } catch (Exception e) {
log.debug("Exception while reading value of attribute " + name, e);
}
} else {
@@ -448,28 +422,24 @@
private boolean setNamedAttribute(Attribute attribute) {
boolean result = false;
if (log.isDebugEnabled())
- log.debug("Invoking set on attribute " + attribute.getName()
- + " with value "
- + attribute.getValue());
+ log.debug("Invoking set on attribute " + attribute.getName() + " with value "
+ + attribute.getValue());
AttributeEntry entry = atts.get(attribute.getName());
if (entry != null) {
try {
entry.invoke(attribute);
result = true;
- }
- catch (Exception e) {
+ } catch (Exception e) {
log.warn("Exception while writing value for attribute " + attribute.getName(), e);
}
} else {
- log.warn("Could not invoke set on attribute " + attribute.getName()
- + " with value "
- + attribute.getValue());
+ log.warn("Could not invoke set on attribute " + attribute.getName() + " with value "
+ + attribute.getValue());
}
return result;
}
-
private String renameToJavaCodingConvention(String fieldName) {
if (fieldName.contains("_")) {
Pattern p = Pattern.compile("_.");
@@ -501,9 +471,8 @@
final Method setMethod;
- public MethodAttributeEntry(final MBeanAttributeInfo info,
- final Method setMethod,
- final Method isOrGetMethod) {
+ public MethodAttributeEntry(final MBeanAttributeInfo info, final Method setMethod,
+ final Method isOrGetMethod) {
super();
this.info = info;
this.setMethod = setMethod;
@@ -512,9 +481,9 @@
public Object invoke(Attribute a) throws Exception {
if (a == null && isOrGetmethod != null)
- return isOrGetmethod.invoke(getObject(), new Object[]{});
+ return isOrGetmethod.invoke(getObject(), new Object[] {});
else if (a != null && setMethod != null)
- return setMethod.invoke(getObject(), new Object[]{a.getValue()});
+ return setMethod.invoke(getObject(), new Object[] { a.getValue() });
else
return null;
}
Modified: trunk/core/src/test/java/org/infinispan/jmx/CacheManagerMBeanTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/jmx/CacheManagerMBeanTest.java 2009-09-09 10:41:41 UTC (rev 799)
+++ trunk/core/src/test/java/org/infinispan/jmx/CacheManagerMBeanTest.java 2009-09-09 10:50:49 UTC (rev 800)
@@ -7,8 +7,10 @@
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.testng.annotations.Test;
+import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.ObjectName;
+import javax.management.ServiceNotFoundException;
/**
* Tests whether the attributes defined by DefaultCacheManager work correct.
@@ -63,4 +65,14 @@
assert attribute.contains("b(");
assert attribute.contains("c(");
}
+
+ public void testInvokeJmxOperationNotExposed() throws Exception {
+ try {
+ server.invoke(name, "stop", new Object[]{}, new String[]{});
+ assert false : "Method not exposed, invocation should have failed";
+ } catch (MBeanException mbe) {
+ assert mbe.getCause() instanceof ServiceNotFoundException;
+ }
+
+ }
}
More information about the infinispan-commits
mailing list