Back to index

munin  2.0.1
AbstractAnnotationGraphsProvider.java
Go to the documentation of this file.
00001 package org.munin.plugin.jmx;
00002 
00003 import java.io.PrintWriter;
00004 import java.lang.annotation.ElementType;
00005 import java.lang.annotation.Retention;
00006 import java.lang.annotation.RetentionPolicy;
00007 import java.lang.annotation.Target;
00008 import java.lang.reflect.AccessibleObject;
00009 import java.lang.reflect.InvocationTargetException;
00010 import java.lang.reflect.Method;
00011 import java.util.Collection;
00012 import java.util.Comparator;
00013 import java.util.TreeSet;
00014 
00015 public abstract class AbstractAnnotationGraphsProvider extends
00016               AbstractGraphsProvider {
00017        
00018        protected AbstractAnnotationGraphsProvider(final Config config) {
00019               super(config);
00020        }
00021 
00022        @Override
00023        public void printConfig(PrintWriter out) {
00024               printGraphConfig(out);
00025               printFieldsConfig(out);
00026        }
00027 
00028        protected void printGraphConfig(PrintWriter out) {
00029               Graph graph = getClass().getAnnotation(Graph.class);
00030               if (graph == null) {
00031                      throw new IllegalArgumentException(getClass()
00032                                    + " doesn't have @Graph annotation");
00033               }
00034               String graphTitle = "JVM (port " + config.getPort() + ") "
00035                             + graph.title();
00036               printGraphConfig(out, graphTitle, graph.vlabel(), graph.info(), graph
00037                             .args(), graph.update(), graph.graph());
00038        }
00039 
00040        protected void printFieldsConfig(PrintWriter out) {
00041               for (AccessibleObject accessible : getFieldObjects()) {
00042                      printFieldConfig(out, accessible);
00043               }
00044        }
00045 
00046        protected void printFieldConfig(PrintWriter out, AccessibleObject accessible) {
00047               Field field = accessible.getAnnotation(Field.class);
00048               String fieldName = getFieldName(accessible);
00049               String fieldLabel = field.label();
00050               if (fieldLabel.length() == 0) {
00051                      fieldLabel = fieldName;
00052               }
00053 
00054               printFieldConfig(out, fieldName, fieldLabel, field.info(),
00055                             field.type(), field.draw(), field.colour(), field.min(), field
00056                                           .max());
00057        }
00058 
00059        private Collection<AccessibleObject> getFieldObjects() {
00060               // ensure methods are sorted by position first, then by name
00061               TreeSet<AccessibleObject> fieldObjects = new TreeSet<AccessibleObject>(
00062                             new Comparator<AccessibleObject>() {
00063 
00064                                    public int compare(AccessibleObject m1, AccessibleObject m2) {
00065                                           Integer pos1 = m1.getAnnotation(Field.class).position();
00066                                           Integer pos2 = m2.getAnnotation(Field.class).position();
00067                                           int result = pos1.compareTo(pos2);
00068                                           if (result == 0) {
00069                                                  result = getFieldName(m1).compareTo(
00070                                                                getFieldName(m2));
00071                                           }
00072                                           return result;
00073                                    }
00074                             });
00075 
00076               for (Method method : getClass().getMethods()) {
00077                      if (method.isAnnotationPresent(Field.class)) {
00078                             fieldObjects.add(method);
00079                      }
00080               }
00081               for (java.lang.reflect.Field field : getClass().getFields()) {
00082                      if (field.isAnnotationPresent(Field.class)) {
00083                             fieldObjects.add(field);
00084                      }
00085               }
00086               return fieldObjects;
00087        }
00088 
00089        protected String getFieldName(AccessibleObject accessible) {
00090               String fieldName = accessible.getAnnotation(Field.class).name();
00091               if (fieldName.length() == 0) {
00092                      String n;
00093                      if (accessible instanceof Method) {
00094                             n = ((Method) accessible).getName();
00095                      } else if (accessible instanceof java.lang.reflect.Field) {
00096                             n = ((java.lang.reflect.Field) accessible).getName();
00097                      } else {
00098                             throw new IllegalArgumentException(
00099                                           "AccessibleObject must be a field or a method: "
00100                                                         + accessible);
00101                      }
00102                      fieldName = n.substring(0, 1).toUpperCase() + n.substring(1);
00103               }
00104               return fieldName;
00105        }
00106 
00107        private Object getFieldValue(AccessibleObject accessible)
00108                      throws IllegalAccessException, InvocationTargetException {
00109               Object value;
00110               if (accessible instanceof Method) {
00111                      value = ((Method) accessible).invoke(this, new Object[0]);
00112               } else if (accessible instanceof java.lang.reflect.Field) {
00113                      value = ((java.lang.reflect.Field) accessible).get(this);
00114               } else {
00115                      throw new IllegalArgumentException(
00116                                    "AccessibleObject must be a field or a method: "
00117                                                  + accessible);
00118               }
00119               return value;
00120        }
00121 
00122        @Override
00123        public void printValues(PrintWriter out) {
00124               try {
00125                      prepareValues();
00126               } catch (Exception e) {
00127                      System.err.println("Failed to prepare values for class "
00128                                    + getClass() + ": " + e.getMessage());
00129                      e.printStackTrace();
00130               }
00131               for (AccessibleObject accessible : getFieldObjects()) {
00132                      printFieldValue(out, accessible);
00133               }
00134        }
00135 
00136        protected void printFieldValue(PrintWriter out, AccessibleObject accessible) {
00137               String fieldName = getFieldName(accessible);
00138               try {
00139                      Object value = getFieldValue(accessible);
00140                      printFieldAttribute(out, fieldName, "value", value);
00141               } catch (Exception e) {
00142                      System.err.println("Failed to get value for field " + fieldName
00143                                    + ": " + e.getMessage());
00144                      e.printStackTrace();
00145               }
00146        }
00147 
00148        protected void prepareValues() throws Exception {
00149               // nothing
00150        }
00151 
00152        @Target(ElementType.TYPE)
00153        @Retention(RetentionPolicy.RUNTIME)
00154        public @interface Graph {
00155               String title();
00156 
00157               String vlabel();
00158 
00159               String info() default "";
00160 
00161               String args() default "";
00162 
00163               boolean update() default true;
00164 
00165               boolean graph() default true;
00166        }
00167 
00168        @Target( { ElementType.METHOD, ElementType.FIELD })
00169        @Retention(RetentionPolicy.RUNTIME)
00170        public @interface Field {
00171               String name() default "";
00172 
00173               String label() default "";
00174 
00175               String info() default "";
00176 
00177               String type() default "";
00178 
00179               double min() default Double.NaN;
00180 
00181               double max() default Double.NaN;
00182 
00183               String draw() default "";
00184 
00185               String colour() default "";
00186 
00187               // Fields that have no explicit position are placed after those that
00188               // have a position. Fields with the same position value are sorted
00189               // alphabetically by name.
00190               int position() default Integer.MAX_VALUE;
00191        }
00192 
00193 }