1 55 56 package org.apache.bsf.util; 57 58 import java.util.*; 59 import java.io.*; 60 import java.beans.*; 61 import java.lang.reflect.*; 62 63 70 public class MethodUtils { 71 72 94 private static class MoreSpecific 95 extends Vector 96 { 97 103 void addItem (Object newEntry) 104 { 105 if(size()==0) 106 addElement(newEntry); 107 else 108 { 109 Class [] newargs=entryGetParameterTypes(newEntry); 110 boolean keep=true; 111 for (Enumeration e = elements(); 112 keep & e.hasMoreElements() ; 113 ) 114 { 115 Object oldEntry=e.nextElement(); 116 Class [] oldargs=entryGetParameterTypes(oldEntry); 118 if(areMethodConvertable(oldargs,newargs)) 119 removeElement(oldEntry); else if(areMethodConvertable(newargs,oldargs)) 121 keep=false; } 124 if(keep) 125 addElement(newEntry); 126 } 127 } 128 129 135 Object getMostSpecific(Class targetClass,String methodName, 136 Class [] argTypes,boolean isStaticReference) 137 throws NoSuchMethodException 138 { 139 if(size()==1) 140 return firstElement(); 141 if(size()>1) 142 { 143 StringBuffer buf=new StringBuffer (); 144 Enumeration e=elements(); 145 buf.append(e.nextElement()); 146 while(e.hasMoreElements()) 147 buf.append(" and ").append(e.nextElement()); 148 throw new NoSuchMethodException (callToString(targetClass, 149 methodName, 150 argTypes, 151 isStaticReference)+ 152 " is ambiguous. It matches "+ 153 buf.toString()); 154 } 155 return null; 156 } 157 } 158 159 162 static private boolean areMethodConvertable(Class [] parms,Class [] args) 163 { 164 if(parms.length!=args.length) 165 return false; 166 167 for(int i=0;i<parms.length;++i) 168 if(!isMethodConvertable(parms[i],args[i])) 169 return false; 170 171 return true; 172 } 173 176 private static String callToString(Class targetClass,String methodName, 177 Class [] argTypes,boolean isStaticReference) 178 { 179 StringBuffer buf = new StringBuffer (); 180 if(isStaticReference) 181 buf.append("static "); 182 buf.append(StringUtils.getClassName(targetClass)); 183 if(methodName!=null) 184 buf.append(".").append(methodName); 185 buf.append("("); 186 if (argTypes != null && argTypes.length>0) { 187 if(false) 188 { 189 } 192 else 193 { 194 buf.append(StringUtils.getClassName(argTypes[0])); 195 for (int i = 1; i < argTypes.length; i++) { 196 buf.append(",").append(StringUtils.getClassName(argTypes[i])); 197 } 198 } 199 } 200 else 201 buf.append("[none]"); 202 buf.append(")"); 203 return buf.toString(); 204 } 205 207 static int entryGetModifiers(Object entry) 208 { 209 return (entry instanceof Method) 210 ? ((Method)entry).getModifiers() 211 : ((Constructor)entry).getModifiers(); 212 } 213 222 224 static String entryGetName(Object entry) 225 { 226 return (entry instanceof Method) 227 ? ((Method)entry).getName() 228 : ((Constructor)entry).getName(); 229 } 230 232 static Class [] entryGetParameterTypes(Object entry) 233 { 234 return (entry instanceof Method) 235 ? ((Method)entry).getParameterTypes() 236 : ((Constructor)entry).getParameterTypes(); 237 } 238 240 static String entryToString(Object entry) 241 { 242 return (entry instanceof Method) 243 ? ((Method)entry).toString() 244 : ((Constructor)entry).toString(); 245 } 246 248 258 static public Constructor getConstructor(Class targetClass, Class [] argTypes) 259 throws SecurityException , NoSuchMethodException 260 { 261 return (Constructor) getEntryPoint(targetClass,null,argTypes,true); 262 } 263 265 287 static private Object getEntryPoint(Class targetClass, 288 String methodName, 289 Class [] argTypes, 290 boolean isStaticReference) 291 throws SecurityException , NoSuchMethodException 292 { 293 Object m=null; 295 296 299 try { 301 if(methodName!=null) 302 { 303 m=targetClass.getMethod (methodName, argTypes); 304 if(isStaticReference && 305 !Modifier.isStatic(entryGetModifiers(m)) ) 306 { 307 throw 308 new NoSuchMethodException (callToString (targetClass, 309 methodName, 310 argTypes, 311 isStaticReference)+ 312 " resolved to instance " + m); 313 } 314 return m; 315 } 316 else 317 return targetClass.getConstructor (argTypes); 318 319 } catch (NoSuchMethodException e) { 320 if(argTypes==null || argTypes.length==0) 322 { 323 throw 324 new NoSuchMethodException (callToString (targetClass, 325 methodName, 326 argTypes, 327 isStaticReference)+ 328 " not found."); 329 } 330 } 332 333 336 Object [] methods; 339 if(methodName!=null) 340 { 341 methods=targetClass.getMethods(); 342 } 343 else 344 { 345 methods=targetClass.getConstructors(); 346 } 347 if(0==methods.length) 348 { 349 throw new NoSuchMethodException ("No methods!"); 350 } 351 352 MoreSpecific best=new MoreSpecific(); 353 for(int i=0;i<methods.length;++i) 354 { 355 Object mi=methods[i]; 356 if ( 357 Modifier.isPublic(entryGetModifiers(mi)) 359 && 360 (methodName==null || entryGetName(mi).equals(methodName) ) 362 && 363 areMethodConvertable(entryGetParameterTypes(mi),argTypes) 365 ) 366 best.addItem(mi); 368 } 369 370 m=best.getMostSpecific(targetClass,methodName,argTypes,isStaticReference); 373 374 if(m==null) 382 { 383 throw new NoSuchMethodException (callToString(targetClass, 384 methodName, 385 argTypes, 386 isStaticReference)+ 387 " -- no signature match"); 388 } 389 390 if( methodName!=null && 391 isStaticReference && 392 !Modifier.isStatic(entryGetModifiers(m)) ) 393 { 394 throw new NoSuchMethodException (callToString(targetClass, 395 methodName, 396 argTypes, 397 isStaticReference)+ 398 " resolved to instance: "+m); 399 } 400 401 return m; 402 } 403 405 415 static public Method getMethod(Class target,String methodName, 416 Class [] argTypes,boolean isStaticReference) 417 throws SecurityException , NoSuchMethodException 418 { 419 return (Method)getEntryPoint(target,methodName,argTypes,isStaticReference); 420 } 421 423 443 static public Method getMethod(Object target,String methodName, 444 Class [] argTypes) 445 throws SecurityException , NoSuchMethodException 446 { 447 boolean staticRef=target instanceof Class ; 448 return getMethod( staticRef ? (Class )target : target.getClass(), 449 methodName,argTypes,staticRef); 450 } 451 461 static private boolean isAssignmentConvertable(Class parm,Class arg) 462 { 463 return 464 (arg.equals(Integer.TYPE) && 465 (parm.equals(Byte.TYPE) || 466 parm.equals(Short.TYPE) || 467 parm.equals(Character.TYPE) 468 ) 469 ) || 470 isMethodConvertable(parm,arg); 471 } 472 489 static private boolean isMethodConvertable(Class parm, Class arg) 490 { 491 if (parm.equals(arg)) return true; 493 494 if (arg == null) 496 { 497 return !parm.isPrimitive(); 498 } 499 500 while(parm.isArray()) 504 { 505 if(!arg.isArray()) 506 return false; else 508 { 509 parm=parm.getComponentType(); 510 arg=arg.getComponentType(); 511 } 512 } 513 if(arg.isArray()) 514 return false; 516 if(parm.isAssignableFrom(arg)) 525 return true; 526 527 532 if(parm.equals(Void.TYPE) || parm.equals(Boolean.TYPE) || 533 arg.equals(Void.TYPE) || arg.equals(Boolean.TYPE)) 534 return false; 535 536 Class [] primTypes={ Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE, 537 Long.TYPE, Float.TYPE, Double.TYPE }; 538 int parmscore,argscore; 539 540 for(parmscore=0;parmscore<primTypes.length;++parmscore) 541 if (parm.equals(primTypes[parmscore])) 542 break; 543 if(parmscore>=primTypes.length) 544 return false; 546 for(argscore=0;argscore<primTypes.length;++argscore) 547 if (arg.equals(primTypes[argscore])) 548 break; 549 if(argscore>=primTypes.length) 550 return false; 552 return (argscore<parmscore && (argscore!=0 || parmscore>2) ); 554 } 555 } 556 | Popular Tags |