1 29 30 package com.caucho.quercus.env; 31 32 import com.caucho.quercus.QuercusException; 33 import com.caucho.quercus.annotation.*; 34 import com.caucho.quercus.expr.*; 35 import com.caucho.quercus.function.Marshal; 36 import com.caucho.quercus.function.MarshalFactory; 37 import com.caucho.quercus.module.ModuleContext; 38 import com.caucho.quercus.parser.QuercusParser; 39 import com.caucho.util.L10N; 40 41 import java.lang.annotation.Annotation ; 42 43 46 abstract public class JavaInvoker 47 extends AbstractJavaMethod 48 { 49 private static final L10N L = new L10N(JavaInvoker.class); 50 51 private static final Object [] NULL_ARGS = new Object [0]; 52 private static final Value [] NULL_VALUES = new Value[0]; 53 54 private final ModuleContext _moduleContext; 55 private final String _name; 56 private final Class [] _param; 57 private final Class _retType; 58 private final Annotation [][] _paramAnn; 59 private final Annotation []_methodAnn; 60 61 private volatile boolean _isInit; 62 63 private boolean _hasEnv; 64 private boolean _hasThis; 65 private Expr [] _defaultExprs; 66 private Marshal [] _marshalArgs; 67 private boolean _hasRestArgs; 68 private Marshal _unmarshalReturn; 69 70 private boolean _isRestReference; 71 72 private boolean _isCallUsesVariableArgs; 73 private boolean _isCallUsesSymbolTable; 74 75 78 public JavaInvoker(ModuleContext moduleContext, 79 String name, 80 Class []param, 81 Annotation [][]paramAnn, 82 Annotation []methodAnn, 83 Class retType) 84 { 85 _moduleContext = moduleContext; 86 _name = name; 87 _param = param; 88 _paramAnn = paramAnn; 89 _methodAnn = methodAnn; 90 _retType = retType; 91 92 } 94 95 public synchronized void init() 96 { 97 if (_isInit) 98 return; 99 100 MarshalFactory marshalFactory = _moduleContext.getMarshalFactory(); 101 ExprFactory exprFactory = _moduleContext.getExprFactory(); 102 103 try { 104 boolean callUsesVariableArgs = false; 105 boolean callUsesSymbolTable = false; 106 boolean returnNullAsFalse = false; 107 108 for (Annotation ann : _methodAnn) { 109 if (VariableArguments.class.isAssignableFrom(ann.annotationType())) { 110 callUsesVariableArgs = true; 111 } 112 113 if (UsesSymbolTable.class.isAssignableFrom(ann.annotationType())) { 114 callUsesSymbolTable = true; 115 } 116 117 if (ReturnNullAsFalse.class.isAssignableFrom(ann.annotationType())) { 118 returnNullAsFalse = true; 119 } 120 } 121 122 _isCallUsesVariableArgs = callUsesVariableArgs; 123 _isCallUsesSymbolTable = callUsesSymbolTable; 124 125 _hasEnv = _param.length > 0 && _param[0].equals(Env.class); 126 int envOffset = _hasEnv ? 1 : 0; 127 128 if (envOffset < _param.length) 129 _hasThis = hasThis(_param[envOffset], _paramAnn[envOffset]); 130 else 131 _hasThis = false; 132 133 if (_hasThis) 134 envOffset++; 135 136 boolean hasRestArgs = false; 137 boolean isRestReference = false; 138 139 if (_param.length > 0 && 140 (_param[_param.length - 1].equals(Value[].class) || 141 _param[_param.length - 1].equals(Object [].class))) { 142 hasRestArgs = true; 143 144 for (Annotation ann : _paramAnn[_param.length - 1]) { 145 if (Reference.class.isAssignableFrom(ann.annotationType())) 146 isRestReference = true; 147 } 148 } 149 150 _hasRestArgs = hasRestArgs; 151 _isRestReference = isRestReference; 152 153 int argLength = _param.length; 154 155 if (_hasRestArgs) 156 argLength -= 1; 157 158 _defaultExprs = new Expr[argLength - envOffset]; 159 160 _marshalArgs = new Marshal[argLength - envOffset]; 161 162 for (int i = 0; i < argLength - envOffset; i++) { 163 boolean isReference = false; 164 boolean isNotNull = false; 165 166 for (Annotation ann : _paramAnn[i + envOffset]) { 167 if (Optional.class.isAssignableFrom(ann.annotationType())) { 168 Optional opt = (Optional) ann; 169 170 if (! opt.value().equals("")) { 171 Expr expr = QuercusParser.parseDefault(opt.value()); 172 173 _defaultExprs[i] = expr; 174 } else 175 _defaultExprs[i] = exprFactory.createDefault(); 176 } else if (Reference.class.isAssignableFrom(ann.annotationType())) { 177 isReference = true; 178 } else if (NotNull.class.isAssignableFrom(ann.annotationType())) { 179 isNotNull = true; 180 } 181 } 182 183 Class argType = _param[i + envOffset]; 184 185 if (isReference) { 186 _marshalArgs[i] = marshalFactory.createReference(); 187 188 if (! Value.class.equals(argType) 189 && ! Var.class.equals(argType)) { 190 throw new QuercusException(L.l("reference must be Value or Var for {0}", 191 _name)); 192 } 193 } 194 else 195 _marshalArgs[i] = marshalFactory.create(argType, isNotNull); 196 } 197 198 _unmarshalReturn = marshalFactory.create(_retType, 199 false, 200 returnNullAsFalse); 201 } finally { 202 _isInit = true; 203 } 204 } 205 206 209 public boolean getHasEnv() 210 { 211 if (! _isInit) 212 init(); 213 214 return _hasEnv; 215 } 216 217 220 public boolean getHasRestArgs() 221 { 222 if (! _isInit) 223 init(); 224 225 return _hasRestArgs; 226 } 227 228 231 public boolean isRestReference() 232 { 233 if (! _isInit) 234 init(); 235 236 return _isRestReference; 237 } 238 239 242 public Marshal getUnmarshalReturn() 243 { 244 if (! _isInit) 245 init(); 246 247 return _unmarshalReturn; 248 } 249 250 253 @Override 254 public boolean isCallUsesVariableArgs() 255 { 256 if (! _isInit) 257 init(); 258 259 return _isCallUsesVariableArgs; 260 } 261 262 265 @Override 266 public boolean isCallUsesSymbolTable() 267 { 268 if (! _isInit) 269 init(); 270 271 return _isCallUsesSymbolTable; 272 } 273 274 277 public boolean isBoolean() 278 { 279 if (! _isInit) 280 init(); 281 282 return _unmarshalReturn.isBoolean(); 283 } 284 285 288 public boolean isString() 289 { 290 if (! _isInit) 291 init(); 292 293 return _unmarshalReturn.isString(); 294 } 295 296 299 public boolean isLong() 300 { 301 if (! _isInit) 302 init(); 303 304 return _unmarshalReturn.isLong(); 305 } 306 307 310 public boolean isDouble() 311 { 312 if (! _isInit) 313 init(); 314 315 return _unmarshalReturn.isDouble(); 316 } 317 318 321 protected Marshal []getMarshalArgs() 322 { 323 if (! _isInit) 324 init(); 325 326 return _marshalArgs; 327 } 328 329 332 protected Annotation [][]getParamAnn() 333 { 334 if (! _isInit) 335 init(); 336 337 return _paramAnn; 338 } 339 340 343 protected Expr []getDefaultExprs() 344 { 345 if (! _isInit) 346 init(); 347 348 return _defaultExprs; 349 } 350 351 354 @Override 355 public Value []evalArguments(Env env, Expr fun, Expr []args) 356 { 357 if (! _isInit) 358 init(); 359 360 Value []values = new Value[args.length]; 361 362 for (int i = 0; i < args.length; i++) { 363 Marshal arg = null; 364 365 if (i < _marshalArgs.length) 366 arg = _marshalArgs[i]; 367 else if (_isRestReference) { 368 values[i] = args[i].evalRef(env); 369 continue; 370 } 371 else { 372 values[i] = args[i].eval(env); 373 continue; 374 } 375 376 if (arg == null) 377 values[i] = args[i].eval(env).copy(); 378 else if (arg.isReference()) 379 values[i] = args[i].evalRef(env); 380 else { 381 values[i] = args[i].eval(env); 383 } 384 } 385 386 return values; 387 } 388 389 public Value call(Env env, Value []value) 390 { 391 return call(env, env.getThis(), value); 392 } 393 394 398 public Value callCopy(Env env, Value []args) 399 { 400 return call(env, args); 401 } 402 403 public Value call(Env env, Value obj, Value []value) 404 { 405 return call(env, obj.toJavaObject(), value); 406 } 407 408 public Value call(Env env, Object obj, Expr []exprs) 409 { 410 if (! _isInit) 411 init(); 412 413 int len = (_defaultExprs.length + 414 (_hasEnv ? 1 : 0) + 415 (_hasThis ? 1 : 0) + 416 (_hasRestArgs ? 1 : 0)); 417 418 Object []values = new Object [len]; 419 420 int k = 0; 421 422 if (_hasEnv) 423 values[k++] = env; 424 if (_hasThis) { 425 values[k++] = (ObjectValue) obj; 426 obj = null; 427 } 428 429 for (int i = 0; i < _marshalArgs.length; i++) { 430 Expr expr; 431 432 if (i < exprs.length && exprs[i] != null) 433 expr = exprs[i]; 434 else { 435 expr = _defaultExprs[i]; 436 437 if (expr == null) 438 expr = _moduleContext.getExprFactory().createRequired(); 439 } 440 441 values[k] = _marshalArgs[i].marshal(env, expr, _param[k]); 442 443 k++; 444 } 445 446 if (_hasRestArgs) { 447 Value []rest; 448 449 int restLen = exprs.length - _marshalArgs.length; 450 451 if (restLen <= 0) 452 rest = NULL_VALUES; 453 else { 454 rest = new Value[restLen]; 455 456 for (int i = _marshalArgs.length; i < exprs.length; i++) { 457 if (_isRestReference) 458 rest[i - _marshalArgs.length] = exprs[i].evalRef(env); 459 else 460 rest[i - _marshalArgs.length] = exprs[i].eval(env); 461 } 462 } 463 464 values[values.length - 1] = rest; 465 } 466 467 Object result = invoke(obj, values); 468 469 return _unmarshalReturn.unmarshal(env, result); 470 } 471 472 public Value call(Env env, Object obj, Value []args) 473 { 474 if (! _isInit) 475 init(); 476 477 int len = _param.length; 478 479 Object []javaArgs = new Object [len]; 480 481 int k = 0; 482 483 if (_hasEnv) 484 javaArgs[k++] = env; 485 486 if (_hasThis) { 487 javaArgs[k++] = (ObjectValue) obj; 488 obj = null; 489 } 490 491 for (int i = 0; i < _marshalArgs.length; i++) { 492 Value value; 493 494 if (i < args.length && args[i] != null) 495 javaArgs[k] = _marshalArgs[i].marshal(env, args[i], _param[k]); 496 else if (_defaultExprs[i] != null) { 497 javaArgs[k] = _marshalArgs[i].marshal(env, 498 _defaultExprs[i], 499 _param[k]); 500 } else { 501 env.warning(L.l("function '{0}' has {1} required arguments, but only {2} were provided", 502 _name, _marshalArgs.length, args.length)); 503 504 javaArgs[k] = _marshalArgs[i].marshal(env, 505 NullValue.NULL, 506 _param[k]); 507 } 508 509 k++; 510 } 511 512 if (_hasRestArgs) { 513 Value []rest; 514 515 int restLen = args.length - _marshalArgs.length; 516 517 if (restLen <= 0) 518 rest = NULL_VALUES; 519 else { 520 rest = new Value[restLen]; 521 522 for (int i = _marshalArgs.length; i < args.length; i++) { 523 if (_isRestReference) 524 rest[i - _marshalArgs.length] = args[i]; 525 else 526 rest[i - _marshalArgs.length] = args[i].toValue(); 527 } 528 } 529 530 javaArgs[k++] = rest; 531 } 532 533 Object result = invoke(obj, javaArgs); 534 535 return _unmarshalReturn.unmarshal(env, result); 536 } 537 538 public Value call(Env env, Object obj) 539 { 540 return call(env, obj, new Value[0]); 541 } 542 543 public Value call(Env env, Object obj, Value a1) 544 { 545 return call(env, obj, new Value[] {a1}); 546 } 547 548 public Value call(Env env, Object obj, Value a1, Value a2) 549 { 550 return call(env, obj, new Value[]{a1, a2}); 551 } 552 553 public Value call(Env env, Object obj, Value a1, Value a2, Value a3) 554 { 555 return call(env, obj, new Value[]{a1, a2, a3}); 556 } 557 558 public Value call(Env env, Object obj, 559 Value a1, Value a2, Value a3, Value a4) 560 { 561 return call(env, obj, new Value[]{a1, a2, a3, a4}); 562 } 563 564 public Value call(Env env, Object obj, 565 Value a1, Value a2, Value a3, Value a4, Value a5) 566 { 567 return call(env, obj, new Value[]{a1, a2, a3, a4, a5}); 568 } 569 570 abstract public Object invoke(Object obj, Object []args); 571 572 private boolean hasThis(Class param, Annotation []ann) 576 { 577 if (! param.isAssignableFrom(ObjectValue.class)) 578 return false; 579 580 for (int i = 0; i < ann.length; i++) { 581 if (This.class.isAssignableFrom(ann[i].annotationType())) 582 return true; 583 } 584 585 return false; 586 } 587 } 588 | Popular Tags |