1 7 8 package com.sun.jmx.mbeanserver; 9 10 import static com.sun.jmx.mbeanserver.Util.*; 11 12 import java.lang.reflect.Method ; 13 import java.util.Arrays ; 14 import java.util.Collection ; 15 import java.util.Comparator ; 16 import java.util.HashSet ; 17 import java.util.LinkedHashMap ; 18 import java.util.List ; 19 import java.util.Map ; 20 import java.util.Set ; 21 22 import javax.management.NotCompliantMBeanException ; 23 24 38 class MBeanAnalyzer<M> { 39 40 static interface MBeanVisitor<M> { 41 public void visitAttribute(String attributeName, 42 M getter, 43 M setter); 44 public void visitOperation(String operationName, 45 M operation); 46 } 47 48 void visit(MBeanVisitor<M> visitor) { 49 for (Map.Entry <String , AttrMethods<M>> entry : attrMap.entrySet()) { 51 String name = entry.getKey(); 52 AttrMethods<M> am = entry.getValue(); 53 visitor.visitAttribute(name, am.getter, am.setter); 54 } 55 56 for (Map.Entry <String , List <M>> entry : opMap.entrySet()) { 58 for (M m : entry.getValue()) 59 visitor.visitOperation(entry.getKey(), m); 60 } 61 } 62 63 64 private Map <String , List <M>> opMap = newInsertionOrderMap(); 65 66 private Map <String , AttrMethods<M>> attrMap = newInsertionOrderMap(); 67 68 private static class AttrMethods<M> { 69 M getter; 70 M setter; 71 } 72 73 79 static <M> MBeanAnalyzer<M> analyzer(Class <?> mbeanInterface, 85 MBeanIntrospector<M> introspector) 86 throws NotCompliantMBeanException { 87 return new MBeanAnalyzer<M>(mbeanInterface, introspector); 88 } 89 90 private MBeanAnalyzer(Class <?> mbeanInterface, 91 MBeanIntrospector<M> introspector) 92 throws NotCompliantMBeanException { 93 if (!mbeanInterface.isInterface()) { 94 throw new NotCompliantMBeanException ("Not an interface: " + 95 mbeanInterface.getName()); 96 } 97 98 try { 99 initMaps(mbeanInterface, introspector); 100 } catch (Exception x) { 101 throw Introspector.throwException(mbeanInterface,x); 102 } 103 } 104 105 private void initMaps(Class <?> mbeanInterface, 108 MBeanIntrospector<M> introspector) throws Exception { 109 final Method [] methodArray = mbeanInterface.getMethods(); 110 111 final List <Method > methods = eliminateCovariantMethods(methodArray); 112 113 115 for (Method m : methods) { 116 String name = m.getName(); 117 118 final M cm = introspector.mFrom(m); 119 120 String attrName = ""; 121 if (name.startsWith("get")) 122 attrName = name.substring(3); 123 else if (name.startsWith("is") 124 && m.getReturnType() == boolean.class) 125 attrName = name.substring(2); 126 127 if (attrName.length() != 0 && m.getParameterTypes().length == 0 128 && m.getReturnType() != void.class) { 129 AttrMethods<M> am = attrMap.get(attrName); 132 if (am == null) 133 am = new AttrMethods<M>(); 134 else { 135 if (am.getter != null) { 136 final String msg = "Attribute " + attrName + 137 " has more than one getter"; 138 throw new NotCompliantMBeanException (msg); 139 } 140 } 141 am.getter = cm; 142 attrMap.put(attrName, am); 143 } else if (name.startsWith("set") && name.length() > 3 144 && m.getParameterTypes().length == 1 && 145 m.getReturnType() == void.class) { 146 attrName = name.substring(3); 148 AttrMethods<M> am = attrMap.get(attrName); 149 if (am == null) 150 am = new AttrMethods<M>(); 151 else if (am.setter != null) { 152 final String msg = "Attribute " + attrName + 153 " has more than one setter"; 154 throw new NotCompliantMBeanException (msg); 155 } 156 am.setter = cm; 157 attrMap.put(attrName, am); 158 } else { 159 List <M> cms = opMap.get(name); 161 if (cms == null) 162 cms = newList(); 163 cms.add(cm); 164 opMap.put(name, cms); 165 } 166 } 167 168 for (Map.Entry <String , AttrMethods<M>> entry : attrMap.entrySet()) { 169 AttrMethods<M> am = entry.getValue(); 170 if (!introspector.consistent(am.getter, am.setter)) { 171 final String msg = "Getter and setter for " + entry.getKey() + 172 " have inconsistent types"; 173 throw new NotCompliantMBeanException (msg); 174 } 175 } 176 } 177 178 188 private static class MethodOrder implements Comparator <Method > { 189 public int compare(Method a, Method b) { 190 final int cmp = a.getName().compareTo(b.getName()); 191 if (cmp != 0) return cmp; 192 final Class <?>[] aparams = a.getParameterTypes(); 193 final Class <?>[] bparams = b.getParameterTypes(); 194 if (aparams.length != bparams.length) 195 return aparams.length - bparams.length; 196 if (!Arrays.equals(aparams, bparams)) { 197 return Arrays.toString(aparams). 198 compareTo(Arrays.toString(bparams)); 199 } 200 final Class <?> aret = a.getReturnType(); 201 final Class <?> bret = b.getReturnType(); 202 if (aret == bret) return 0; 203 204 if (aret.isAssignableFrom(bret)) 206 return -1; 207 return +1; } 209 public final static MethodOrder instance = new MethodOrder(); 210 } 211 212 213 219 static List <Method > 220 eliminateCovariantMethods(Method [] methodArray) { 221 225 final int len = methodArray.length; 226 final Method [] sorted = methodArray.clone(); 227 Arrays.sort(sorted,MethodOrder.instance); 228 final Set <Method > overridden = newSet(); 229 for (int i=1;i<len;i++) { 230 final Method m0 = sorted[i-1]; 231 final Method m1 = sorted[i]; 232 233 if (!m0.getName().equals(m1.getName())) continue; 235 236 if (Arrays.equals(m0.getParameterTypes(), 240 m1.getParameterTypes())) { 241 overridden.add(m0); 242 } 243 } 244 245 final List <Method > methods = newList(Arrays.asList(methodArray)); 246 methods.removeAll(overridden); 247 return methods; 248 } 249 250 251 } 252 | Popular Tags |