1 package org.jgroups.blocks; 2 3 4 import org.apache.commons.logging.Log; 5 import org.apache.commons.logging.LogFactory; 6 7 import java.io.Externalizable ; 8 import java.io.IOException ; 9 import java.io.ObjectInput ; 10 import java.io.ObjectOutput ; 11 import java.lang.reflect.InvocationTargetException ; 12 import java.lang.reflect.Method ; 13 import java.util.List ; 14 import java.util.ArrayList ; 15 import java.util.Iterator ; 16 17 18 19 20 27 public class MethodCall implements Externalizable { 28 29 static final long serialVersionUID=7873471327078957662L; 30 31 32 protected String method_name=null; 33 34 35 protected Object [] args=null; 36 37 38 protected Class [] types=null; 39 40 41 protected String [] signature=null; 42 43 44 protected Method method=null; 45 46 protected static final Log log=LogFactory.getLog(MethodCall.class); 47 48 49 protected short mode=OLD; 50 51 52 protected static final short OLD=1; 53 54 55 protected static final short METHOD=2; 56 57 58 protected static final short TYPES=3; 59 60 61 protected static final short SIGNATURE=4; 62 63 64 68 public MethodCall() { 69 } 70 71 72 public MethodCall(Method method) { 73 this(method, null); 74 } 75 76 public MethodCall(Method method, Object [] arguments) { 77 init(method); 78 if(arguments != null) args=arguments; 79 } 80 81 87 public MethodCall(String method_name, Object [] args) { 88 this.method_name=method_name; 89 this.mode=OLD; 90 this.args=args; 91 } 92 93 94 public MethodCall(String method_name, Object [] args, Class [] types) { 95 this.method_name=method_name; 96 this.args=args; 97 this.types=types; 98 this.mode=TYPES; 99 } 100 101 public MethodCall(String method_name, Object [] args, String [] signature) { 102 this.method_name=method_name; 103 this.args=args; 104 this.signature=signature; 105 this.mode=SIGNATURE; 106 } 107 108 void init(Method method) { 109 this.method=method; 110 this.mode=METHOD; 111 method_name=method.getName(); 112 } 113 114 115 public int getMode() { 116 return mode; 117 } 118 119 120 121 125 public String getName() { 126 return method_name; 127 } 128 129 134 public void setName(String n) { 135 method_name=n; 136 } 137 138 142 public Object [] getArgs() { 143 return args; 144 } 145 146 public void setArgs(Object [] args) { 147 if(args != null) 148 this.args=args; 149 } 150 151 public Method getMethod() { 152 return method; 153 } 154 155 156 157 158 164 Method findMethod(Class target_class) throws Exception { 165 int len=args != null? args.length : 0; 166 Method m; 167 168 Method [] methods=getAllMethods(target_class); 169 for(int i=0; i < methods.length; i++) { 170 m=methods[i]; 171 if(m.getName().equals(method_name)) { 172 if(m.getParameterTypes().length == len) 173 return m; 174 } 175 } 176 177 return null; 178 } 179 180 181 185 Method [] getAllMethods(Class target) { 186 187 Class superclass = target; 188 List methods = new ArrayList (); 189 int size = 0; 190 191 while(superclass != null) { 192 Method [] m = superclass.getDeclaredMethods(); 193 methods.add(m); 194 size += m.length; 195 superclass = superclass.getSuperclass(); 196 } 197 198 Method [] result = new Method [size]; 199 int index = 0; 200 for(Iterator i = methods.iterator(); i.hasNext();) { 201 Method [] m = (Method [])i.next(); 202 System.arraycopy(m, 0, result, index, m.length); 203 index += m.length; 204 } 205 return result; 206 } 207 208 215 Method getMethod(Class target, String methodName, Class [] types) { 216 217 if (types == null) { 218 types = new Class [0]; 219 } 220 221 Method [] methods = getAllMethods(target); 222 methods: for(int i = 0; i < methods.length; i++) { 223 Method m = methods[i]; 224 if (!methodName.equals(m.getName())) { 225 continue methods; 226 } 227 Class [] parameters = m.getParameterTypes(); 228 if (types.length != parameters.length) { 229 continue methods; 230 } 231 for(int j = 0; j < types.length; j++) { 232 if (!types[j].equals(parameters[j])) { 233 continue methods; 234 } 235 } 236 return m; 237 } 238 return null; 239 } 240 241 242 249 public Object invoke(Object target) throws Throwable { 250 Class cl; 251 Method meth=null; 252 Object retval=null; 253 254 255 if(method_name == null || target == null) { 256 if(log.isErrorEnabled()) log.error("method name or target is null"); 257 return null; 258 } 259 cl=target.getClass(); 260 try { 261 switch(mode) { 262 case OLD: 263 meth=findMethod(cl); 264 break; 265 case METHOD: 266 if(this.method != null) 267 meth=this.method; 268 break; 269 case TYPES: 270 meth = getMethod(cl, method_name, types); 272 break; 273 case SIGNATURE: 274 Class [] mytypes=null; 275 if(signature != null) 276 mytypes=getTypesFromString(cl, signature); 277 meth = getMethod(cl, method_name, mytypes); 279 break; 280 default: 281 if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid"); 282 break; 283 } 284 285 if(meth != null) { 286 retval=meth.invoke(target, args); 287 } 288 else { 289 if(log.isErrorEnabled()) log.error("method " + method_name + " not found"); 290 } 291 return retval; 292 } 293 catch(InvocationTargetException inv_ex) { 294 throw inv_ex.getTargetException(); 295 } 296 catch(NoSuchMethodException no) { 297 StringBuffer sb=new StringBuffer (); 298 sb.append("found no method called ").append(method_name).append(" in class "); 299 sb.append(cl.getName()).append(" with ("); 300 if(args != null) { 301 for(int i=0; i < args.length; i++) { 302 if(i > 0) 303 sb.append(", "); 304 sb.append((args[i] != null)? args[i].getClass().getName() : "null"); 305 } 306 } 307 sb.append(") formal parameters"); 308 log.error(sb.toString()); 309 throw no; 310 } 311 catch(Throwable e) { 312 if(log.isErrorEnabled()) log.error("exception in invoke()", e); 314 throw e; 315 } 316 } 317 318 public Object invoke(Object target, Object [] args) throws Throwable { 319 if(args != null) 320 this.args=args; 321 return invoke(target); 322 } 323 324 325 Class [] getTypesFromString(Class cl, String [] signature) throws Exception { 326 String name; 327 Class parameter; 328 Class [] mytypes=new Class [signature.length]; 329 330 for(int i=0; i < signature.length; i++) { 331 name=signature[i]; 332 if("long".equals(name)) 333 parameter=long.class; 334 else if("int".equals(name)) 335 parameter=int.class; 336 else if("short".equals(name)) 337 parameter=short.class; 338 else if("char".equals(name)) 339 parameter=char.class; 340 else if("byte".equals(name)) 341 parameter=byte.class; 342 else if("float".equals(name)) 343 parameter=float.class; 344 else if("double".equals(name)) 345 parameter=double.class; 346 else if("boolean".equals(name)) 347 parameter=boolean.class; 348 else 349 parameter=Class.forName(name, false, cl.getClassLoader()); 350 mytypes[i]=parameter; 351 } 352 return mytypes; 353 } 354 355 356 public String toString() { 357 StringBuffer ret=new StringBuffer (); 358 boolean first=true; 359 ret.append(method_name).append('('); 360 if(args != null) { 361 for(int i=0; i < args.length; i++) { 362 if(first) { 363 first=false; 364 } 365 else { 366 ret.append(", "); 367 } 368 ret.append(args[i]); 369 } 370 } 371 ret.append(')'); 372 return ret.toString(); 373 } 374 375 public String toStringDetails() { 376 StringBuffer ret=new StringBuffer (); 377 ret.append("MethodCall (name=" + method_name); 378 ret.append(", number of args=" + (args != null? args.length : 0) + ')'); 379 if(args != null) { 380 ret.append("\nArgs:"); 381 for(int i=0; i < args.length; i++) { 382 ret.append("\n[" + args[i] + " (" + 383 (args[i] != null? args[i].getClass().getName() : "null") + ")]"); 384 } 385 } 386 return ret.toString(); 387 } 388 389 390 public void writeExternal(ObjectOutput out) throws IOException { 391 out.writeUTF(method_name); 392 out.writeObject(args); 393 out.writeShort(mode); 394 395 switch(mode) { 396 case OLD: 397 break; 398 case METHOD: 399 out.writeObject(method.getParameterTypes()); 400 out.writeObject(method.getDeclaringClass()); 401 break; 402 case TYPES: 403 out.writeObject(types); 404 break; 405 case SIGNATURE: 406 out.writeObject(signature); 407 break; 413 default: 414 if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid"); 415 break; 416 } 417 } 418 419 public void readExternal(ObjectInput in) throws IOException , ClassNotFoundException { 420 method_name=in.readUTF(); 421 args=(Object [])in.readObject(); 422 mode=in.readShort(); 423 424 switch(mode) { 425 case OLD: 426 break; 427 case METHOD: 428 Class [] parametertypes=(Class [])in.readObject(); 429 Class declaringclass=(Class )in.readObject(); 430 try { 431 method=declaringclass.getDeclaredMethod(method_name, parametertypes); 432 } 433 catch(NoSuchMethodException e) { 434 throw new IOException (e.toString()); 435 } 436 break; 437 case TYPES: 438 types=(Class [])in.readObject(); 439 break; 440 case SIGNATURE: 441 signature=(String [])in.readObject(); 442 break; 450 default: 451 if(log.isErrorEnabled()) log.error("mode " + mode + " is invalid"); 452 break; 453 } 454 } 455 456 457 458 459 } 460 461 462 463 | Popular Tags |