1// 2// ======================================================================== 3// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. 4// ------------------------------------------------------------------------ 5// All rights reserved. This program and the accompanying materials 6// are made available under the terms of the Eclipse Public License v1.0 7// and Apache License v2.0 which accompanies this distribution. 8// 9// The Eclipse Public License is available at 10// http://www.eclipse.org/legal/epl-v10.html 11// 12// The Apache License v2.0 is available at 13// http://www.opensource.org/licenses/apache2.0.php 14// 15// You may elect to redistribute this code under either of these licenses. 16// ======================================================================== 17// 18 19package org.eclipse.jetty.util; 20 21import java.lang.reflect.Field; 22import java.lang.reflect.Member; 23import java.lang.reflect.Method; 24import java.lang.reflect.Modifier; 25import java.util.Arrays; 26import java.util.List; 27 28/** 29 * IntrospectionUtil 30 * 31 * 32 */ 33public class IntrospectionUtil 34{ 35 36 public static boolean isJavaBeanCompliantSetter (Method method) 37 { 38 if (method == null) 39 return false; 40 41 if (method.getReturnType() != Void.TYPE) 42 return false; 43 44 if (!method.getName().startsWith("set")) 45 return false; 46 47 if (method.getParameterTypes().length != 1) 48 return false; 49 50 return true; 51 } 52 53 public static Method findMethod (Class<?> clazz, String methodName, Class<?>[] args, boolean checkInheritance, boolean strictArgs) 54 throws NoSuchMethodException 55 { 56 if (clazz == null) 57 throw new NoSuchMethodException("No class"); 58 if (methodName==null || methodName.trim().equals("")) 59 throw new NoSuchMethodException("No method name"); 60 61 Method method = null; 62 Method[] methods = clazz.getDeclaredMethods(); 63 for (int i=0;i<methods.length && method==null;i++) 64 { 65 if (methods[i].getName().equals(methodName) && checkParams(methods[i].getParameterTypes(), (args==null?new Class[] {}:args), strictArgs)) 66 { 67 method = methods[i]; 68 } 69 70 } 71 if (method!=null) 72 { 73 return method; 74 } 75 else if (checkInheritance) 76 return findInheritedMethod(clazz.getPackage(), clazz.getSuperclass(), methodName, args, strictArgs); 77 else 78 throw new NoSuchMethodException("No such method "+methodName+" on class "+clazz.getName()); 79 80 } 81 82 83 84 85 86 public static Field findField (Class<?> clazz, String targetName, Class<?> targetType, boolean checkInheritance, boolean strictType) 87 throws NoSuchFieldException 88 { 89 if (clazz == null) 90 throw new NoSuchFieldException("No class"); 91 if (targetName==null) 92 throw new NoSuchFieldException("No field name"); 93 94 try 95 { 96 Field field = clazz.getDeclaredField(targetName); 97 if (strictType) 98 { 99 if (field.getType().equals(targetType)) 100 return field; 101 } 102 else 103 { 104 if (field.getType().isAssignableFrom(targetType)) 105 return field; 106 } 107 if (checkInheritance) 108 { 109 return findInheritedField(clazz.getPackage(), clazz.getSuperclass(), targetName, targetType, strictType); 110 } 111 else 112 throw new NoSuchFieldException("No field with name "+targetName+" in class "+clazz.getName()+" of type "+targetType); 113 } 114 catch (NoSuchFieldException e) 115 { 116 return findInheritedField(clazz.getPackage(),clazz.getSuperclass(), targetName,targetType,strictType); 117 } 118 } 119 120 121 122 123 124 public static boolean isInheritable (Package pack, Member member) 125 { 126 if (pack==null) 127 return false; 128 if (member==null) 129 return false; 130 131 int modifiers = member.getModifiers(); 132 if (Modifier.isPublic(modifiers)) 133 return true; 134 if (Modifier.isProtected(modifiers)) 135 return true; 136 if (!Modifier.isPrivate(modifiers) && pack.equals(member.getDeclaringClass().getPackage())) 137 return true; 138 139 return false; 140 } 141 142 143 144 145 public static boolean checkParams (Class<?>[] formalParams, Class<?>[] actualParams, boolean strict) 146 { 147 if (formalParams==null) 148 return actualParams==null; 149 if (actualParams==null) 150 return false; 151 152 if (formalParams.length!=actualParams.length) 153 return false; 154 155 if (formalParams.length==0) 156 return true; 157 158 int j=0; 159 if (strict) 160 { 161 while (j<formalParams.length && formalParams[j].equals(actualParams[j])) 162 j++; 163 } 164 else 165 { 166 while ((j<formalParams.length) && (formalParams[j].isAssignableFrom(actualParams[j]))) 167 { 168 j++; 169 } 170 } 171 172 if (j!=formalParams.length) 173 { 174 return false; 175 } 176 177 return true; 178 } 179 180 181 public static boolean isSameSignature (Method methodA, Method methodB) 182 { 183 if (methodA==null) 184 return false; 185 if (methodB==null) 186 return false; 187 188 List<Class<?>> parameterTypesA = Arrays.asList(methodA.getParameterTypes()); 189 List<Class<?>> parameterTypesB = Arrays.asList(methodB.getParameterTypes()); 190 191 if (methodA.getName().equals(methodB.getName()) 192 && 193 parameterTypesA.containsAll(parameterTypesB)) 194 return true; 195 196 return false; 197 } 198 199 public static boolean isTypeCompatible (Class<?> formalType, Class<?> actualType, boolean strict) 200 { 201 if (formalType==null) 202 return actualType==null; 203 if (actualType==null) 204 return false; 205 206 if (strict) 207 return formalType.equals(actualType); 208 else 209 return formalType.isAssignableFrom(actualType); 210 } 211 212 213 214 215 public static boolean containsSameMethodSignature (Method method, Class<?> c, boolean checkPackage) 216 { 217 if (checkPackage) 218 { 219 if (!c.getPackage().equals(method.getDeclaringClass().getPackage())) 220 return false; 221 } 222 223 boolean samesig = false; 224 Method[] methods = c.getDeclaredMethods(); 225 for (int i=0; i<methods.length && !samesig; i++) 226 { 227 if (IntrospectionUtil.isSameSignature(method, methods[i])) 228 samesig = true; 229 } 230 return samesig; 231 } 232 233 234 public static boolean containsSameFieldName(Field field, Class<?> c, boolean checkPackage) 235 { 236 if (checkPackage) 237 { 238 if (!c.getPackage().equals(field.getDeclaringClass().getPackage())) 239 return false; 240 } 241 242 boolean sameName = false; 243 Field[] fields = c.getDeclaredFields(); 244 for (int i=0;i<fields.length && !sameName; i++) 245 { 246 if (fields[i].getName().equals(field.getName())) 247 sameName = true; 248 } 249 return sameName; 250 } 251 252 253 254 protected static Method findInheritedMethod (Package pack, Class<?> clazz, String methodName, Class<?>[] args, boolean strictArgs) 255 throws NoSuchMethodException 256 { 257 if (clazz==null) 258 throw new NoSuchMethodException("No class"); 259 if (methodName==null) 260 throw new NoSuchMethodException("No method name"); 261 262 Method method = null; 263 Method[] methods = clazz.getDeclaredMethods(); 264 for (int i=0;i<methods.length && method==null;i++) 265 { 266 if (methods[i].getName().equals(methodName) 267 && isInheritable(pack,methods[i]) 268 && checkParams(methods[i].getParameterTypes(), args, strictArgs)) 269 method = methods[i]; 270 } 271 if (method!=null) 272 { 273 return method; 274 } 275 else 276 return findInheritedMethod(clazz.getPackage(), clazz.getSuperclass(), methodName, args, strictArgs); 277 } 278 279 protected static Field findInheritedField (Package pack, Class<?> clazz, String fieldName, Class<?> fieldType, boolean strictType) 280 throws NoSuchFieldException 281 { 282 if (clazz==null) 283 throw new NoSuchFieldException ("No class"); 284 if (fieldName==null) 285 throw new NoSuchFieldException ("No field name"); 286 try 287 { 288 Field field = clazz.getDeclaredField(fieldName); 289 if (isInheritable(pack, field) && isTypeCompatible(fieldType, field.getType(), strictType)) 290 return field; 291 else 292 return findInheritedField(clazz.getPackage(), clazz.getSuperclass(),fieldName, fieldType, strictType); 293 } 294 catch (NoSuchFieldException e) 295 { 296 return findInheritedField(clazz.getPackage(), clazz.getSuperclass(),fieldName, fieldType, strictType); 297 } 298 } 299 300} 301