1 33 34 package bsh; 35 36 import java.lang.reflect.Method ; 37 import java.lang.reflect.InvocationTargetException ; 38 39 50 54 public class BshMethod 55 implements java.io.Serializable 56 { 57 63 NameSpace declaringNameSpace; 64 65 67 Modifiers modifiers; 68 private String name; 69 private Class creturnType; 70 71 private String [] paramNames; 73 private int numArgs; 74 private Class [] cparamTypes; 75 76 BSHBlock methodBody; 78 79 private Method javaMethod; 81 private Object javaObject; 82 83 85 BshMethod( 86 BSHMethodDeclaration method, 87 NameSpace declaringNameSpace, Modifiers modifiers ) 88 { 89 this( method.name, method.returnType, method.paramsNode.getParamNames(), 90 method.paramsNode.paramTypes, method.blockNode, declaringNameSpace, 91 modifiers ); 92 } 93 94 BshMethod( 95 String name, Class returnType, String [] paramNames, 96 Class [] paramTypes, BSHBlock methodBody, 97 NameSpace declaringNameSpace, Modifiers modifiers 98 ) { 99 this.name = name; 100 this.creturnType = returnType; 101 this.paramNames = paramNames; 102 if ( paramNames != null ) 103 this.numArgs = paramNames.length; 104 this.cparamTypes = paramTypes; 105 this.methodBody = methodBody; 106 this.declaringNameSpace = declaringNameSpace; 107 this.modifiers = modifiers; 108 } 109 110 114 BshMethod( Method method, Object object ) 115 { 116 this( method.getName(), method.getReturnType(), null, 117 method.getParameterTypes(), null, 118 null, null ); 119 120 this.javaMethod = method; 121 this.javaObject = object; 122 } 123 124 125 130 134 public Class [] getParameterTypes() { return cparamTypes; } 135 public String [] getParameterNames() { return paramNames; } 136 137 142 146 public Class getReturnType() { return creturnType; } 147 148 public Modifiers getModifiers() { return modifiers; } 149 150 public String getName() { return name; } 151 152 157 public Object invoke( 158 Object [] argValues, Interpreter interpreter ) 159 throws EvalError 160 { 161 return invoke( argValues, interpreter, null, null, false ); 162 } 163 164 181 public Object invoke( 182 Object [] argValues, Interpreter interpreter, CallStack callstack, 183 SimpleNode callerInfo ) 184 throws EvalError 185 { 186 return invoke( argValues, interpreter, callstack, callerInfo, false ); 187 } 188 189 210 Object invoke( 211 Object [] argValues, Interpreter interpreter, CallStack callstack, 212 SimpleNode callerInfo, boolean overrideNameSpace ) 213 throws EvalError 214 { 215 if ( argValues != null ) 216 for (int i=0; i<argValues.length; i++) 217 if ( argValues[i] == null ) 218 throw new Error ("HERE!"); 219 220 if ( javaMethod != null ) 221 try { 222 return Reflect.invokeMethod( 223 javaMethod, javaObject, argValues ); 224 } catch ( ReflectError e ) { 225 throw new EvalError( 226 "Error invoking Java method: "+e, callerInfo, callstack ); 227 } catch ( InvocationTargetException e2 ) { 228 throw new TargetError( 229 "Exception invoking imported object method.", 230 e2, callerInfo, callstack, true ); 231 } 232 233 if ( modifiers != null && modifiers.hasModifier("synchronized") ) 235 { 236 Object lock; 240 if ( declaringNameSpace.isClass ) 241 { 242 try { 243 lock = declaringNameSpace.getClassInstance(); 244 } catch ( UtilEvalError e ) { 245 throw new InterpreterError( 246 "Can't get class instance for synchronized method."); 247 } 248 } else 249 lock = declaringNameSpace.getThis(interpreter); 251 synchronized( lock ) 252 { 253 return invokeImpl( 254 argValues, interpreter, callstack, 255 callerInfo, overrideNameSpace ); 256 } 257 } else 258 return invokeImpl( argValues, interpreter, callstack, callerInfo, 259 overrideNameSpace ); 260 } 261 262 private Object invokeImpl( 263 Object [] argValues, Interpreter interpreter, CallStack callstack, 264 SimpleNode callerInfo, boolean overrideNameSpace ) 265 throws EvalError 266 { 267 Class returnType = getReturnType(); 268 Class [] paramTypes = getParameterTypes(); 269 270 if ( callstack == null ) 272 callstack = new CallStack( declaringNameSpace ); 273 274 if ( argValues == null ) 275 argValues = new Object [] { }; 276 277 if ( argValues.length != numArgs ) 279 { 280 294 throw new EvalError( 295 "Wrong number of arguments for local method: " 296 + name, callerInfo, callstack ); 297 } 298 299 NameSpace localNameSpace; 301 if ( overrideNameSpace ) 302 localNameSpace = callstack.top(); 303 else 304 { 305 localNameSpace = new NameSpace( declaringNameSpace, name ); 306 localNameSpace.isMethod = true; 307 } 308 localNameSpace.setNode( callerInfo ); 310 311 for(int i=0; i<numArgs; i++) 313 { 314 if ( paramTypes[i] != null ) 316 { 317 try { 318 argValues[i] = 319 Types.castObject( argValues[i], paramTypes[i], Types.ASSIGNMENT ); 321 } 322 catch( UtilEvalError e) { 323 throw new EvalError( 324 "Invalid argument: " 325 + "`"+paramNames[i]+"'" + " for method: " 326 + name + " : " + 327 e.getMessage(), callerInfo, callstack ); 328 } 329 try { 330 localNameSpace.setTypedVariable( paramNames[i], 331 paramTypes[i], argValues[i], null); 332 } catch ( UtilEvalError e2 ) { 333 throw e2.toEvalError( "Typed method parameter assignment", 334 callerInfo, callstack ); 335 } 336 } 337 else { 340 if ( argValues[i] == Primitive.VOID) 342 throw new EvalError( 343 "Undefined variable or class name, parameter: " + 344 paramNames[i] + " to method: " 345 + name, callerInfo, callstack ); 346 else 347 try { 348 localNameSpace.setLocalVariable( 349 paramNames[i], argValues[i], 350 interpreter.getStrictJava() ); 351 } catch ( UtilEvalError e3 ) { 352 throw e3.toEvalError( callerInfo, callstack ); 353 } 354 } 355 } 356 357 if ( !overrideNameSpace ) 359 callstack.push( localNameSpace ); 360 361 Object ret = methodBody.eval( 363 callstack, interpreter, true ); 364 365 CallStack returnStack = callstack.copy(); 367 368 if ( !overrideNameSpace ) 370 callstack.pop(); 371 372 ReturnControl retControl = null; 373 if ( ret instanceof ReturnControl ) 374 { 375 retControl = (ReturnControl)ret; 376 377 if ( retControl.kind == retControl.RETURN ) 379 ret = ((ReturnControl)ret).value; 380 else 381 throw new EvalError("'continue' or 'break' in method body", 383 retControl.returnPoint, returnStack ); 384 385 if ( returnType == Void.TYPE && ret != Primitive.VOID ) 388 throw new EvalError( "Cannot return value from void method", 389 retControl.returnPoint, returnStack); 390 } 391 392 if ( returnType != null ) 393 { 394 if ( returnType == Void.TYPE ) 396 return Primitive.VOID; 397 398 try { 400 ret = 401 Types.castObject( ret, returnType, Types.ASSIGNMENT ); 403 } catch( UtilEvalError e ) 404 { 405 SimpleNode node = callerInfo; 408 if ( retControl != null ) 409 node = retControl.returnPoint; 410 throw e.toEvalError( 411 "Incorrect type returned from method: " 412 + name + e.getMessage(), node, callstack ); 413 } 414 } 415 416 return ret; 417 } 418 419 public boolean hasModifier( String name ) { 420 return modifiers != null && modifiers.hasModifier(name); 421 } 422 423 public String toString() { 424 return "Scripted Method: " 425 + StringUtil.methodString( name, getParameterTypes() ); 426 } 427 428 } 429 | Popular Tags |