1 package org.apache.velocity.runtime.parser.node; 2 3 18 19 import java.io.Writer ; 20 import java.io.IOException ; 21 import java.lang.reflect.InvocationTargetException ; 22 23 import org.apache.velocity.context.Context; 24 import org.apache.velocity.context.InternalContextAdapter; 25 import org.apache.velocity.runtime.RuntimeConstants; 26 import org.apache.velocity.runtime.exception.ReferenceException; 27 import org.apache.velocity.runtime.parser.*; 28 29 import org.apache.velocity.util.introspection.VelPropertySet; 30 import org.apache.velocity.util.introspection.Info; 31 32 import org.apache.velocity.exception.MethodInvocationException; 33 34 import org.apache.velocity.app.event.EventCartridge; 35 36 49 public class ASTReference extends SimpleNode 50 { 51 52 private static final int NORMAL_REFERENCE = 1; 53 private static final int FORMAL_REFERENCE = 2; 54 private static final int QUIET_REFERENCE = 3; 55 private static final int RUNT = 4; 56 57 private int referenceType; 58 private String nullString; 59 private String rootString; 60 private boolean escaped = false; 61 private boolean computableReference = true; 62 private String escPrefix = ""; 63 private String morePrefix = ""; 64 private String identifier = ""; 65 66 private String literal = null; 67 68 private int numChildren = 0; 69 70 protected Info uberInfo; 71 72 public ASTReference(int id) 73 { 74 super(id); 75 } 76 77 public ASTReference(Parser p, int id) 78 { 79 super(p, id); 80 } 81 82 83 public Object jjtAccept(ParserVisitor visitor, Object data) 84 { 85 return visitor.visit(this, data); 86 } 87 88 public Object init(InternalContextAdapter context, Object data) 89 throws Exception 90 { 91 94 95 super.init(context, data); 96 97 102 103 rootString = getRoot(); 104 105 numChildren = jjtGetNumChildren(); 106 107 110 111 if (numChildren > 0 ) 112 { 113 identifier = jjtGetChild(numChildren - 1).getFirstToken().image; 114 } 115 116 119 120 uberInfo = new Info(context.getCurrentTemplateName(), 121 getLine(),getColumn()); 122 123 return data; 124 } 125 126 129 public String getRootString() 130 { 131 return rootString; 132 } 133 134 140 public Object execute(Object o, InternalContextAdapter context) 141 throws MethodInvocationException 142 { 143 144 if (referenceType == RUNT) 145 return null; 146 147 150 151 Object result = getVariableValue(context, rootString); 152 153 if (result == null) 154 { 155 return null; 156 } 157 158 170 171 try 172 { 173 for (int i = 0; i < numChildren; i++) 174 { 175 result = jjtGetChild(i).execute(result,context); 176 177 if (result == null) 178 { 179 return null; 180 } 181 } 182 183 return result; 184 } 185 catch(MethodInvocationException mie) 186 { 187 190 191 rsvc.error("Method " + mie.getMethodName() 192 + " threw exception for reference $" 193 + rootString 194 + " in template " + context.getCurrentTemplateName() 195 + " at " + " [" + this.getLine() + "," 196 + this.getColumn() + "]"); 197 198 mie.setReferenceName(rootString); 199 throw mie; 200 } 201 } 202 203 210 public boolean render(InternalContextAdapter context, Writer writer) 211 throws IOException , MethodInvocationException 212 { 213 214 if (referenceType == RUNT) 215 { 216 writer.write(rootString); 217 return true; 218 } 219 220 Object value = execute(null, context); 221 222 227 228 if (escaped) 229 { 230 if (value == null) 231 { 232 writer.write(escPrefix); 233 writer.write("\\"); 234 writer.write(nullString); 235 } 236 else 237 { 238 writer.write(escPrefix); 239 writer.write(nullString); 240 } 241 242 return true; 243 } 244 245 250 251 EventCartridge ec = context.getEventCartridge(); 252 253 if (ec != null) 254 { 255 value = ec.referenceInsert(literal(), value); 256 } 257 258 261 262 if (value == null) 263 { 264 267 268 writer.write(escPrefix); 269 writer.write(escPrefix); 270 writer.write(morePrefix); 271 writer.write(nullString); 272 273 if (referenceType != QUIET_REFERENCE 274 && rsvc.getBoolean(RuntimeConstants.RUNTIME_LOG_REFERENCE_LOG_INVALID, 275 true)) 276 { 277 rsvc.warn(new ReferenceException("reference : template = " 278 + context.getCurrentTemplateName(), this)); 279 } 280 281 return true; 282 } 283 else 284 { 285 288 289 writer.write(escPrefix); 290 writer.write(morePrefix); 291 writer.write(value.toString()); 292 293 return true; 294 } 295 } 296 297 304 public boolean evaluate(InternalContextAdapter context) 305 throws MethodInvocationException 306 { 307 Object value = execute(null, context); 308 309 if (value == null) 310 { 311 return false; 312 } 313 else if (value instanceof Boolean ) 314 { 315 if (((Boolean ) value).booleanValue()) 316 return true; 317 else 318 return false; 319 } 320 else 321 return true; 322 } 323 324 public Object value(InternalContextAdapter context) 325 throws MethodInvocationException 326 { 327 return (computableReference ? execute(null, context) : null); 328 } 329 330 340 public boolean setValue( InternalContextAdapter context, Object value) 341 throws MethodInvocationException 342 { 343 if (jjtGetNumChildren() == 0) 344 { 345 context.put(rootString, value); 346 return true; 347 } 348 349 354 355 Object result = getVariableValue(context, rootString); 356 357 if (result == null) 358 { 359 rsvc.error(new ReferenceException("reference set : template = " 360 + context.getCurrentTemplateName(), this)); 361 return false; 362 } 363 364 367 368 for (int i = 0; i < numChildren - 1; i++) 369 { 370 result = jjtGetChild(i).execute(result, context); 371 372 if (result == null) 373 { 374 rsvc.error(new ReferenceException("reference set : template = " 375 + context.getCurrentTemplateName(), this)); 376 return false; 377 } 378 } 379 380 385 386 try 387 { 388 VelPropertySet vs = 389 rsvc.getUberspect().getPropertySet(result, identifier, 390 value, uberInfo); 391 392 if (vs == null) 393 return false; 394 395 vs.invoke(result, value); 396 } 397 catch(InvocationTargetException ite) 398 { 399 402 403 throw new MethodInvocationException( 404 "ASTReference : Invocation of method '" 405 + identifier + "' in " + result.getClass() 406 + " threw exception " 407 + ite.getTargetException().getClass(), 408 ite.getTargetException(), identifier ); 409 } 410 catch(Exception e) 411 { 412 415 rsvc.error("ASTReference setValue() : exception : " + e 416 + " template = " + context.getCurrentTemplateName() 417 + " [" + this.getLine() + "," + this.getColumn() + "]"); 418 return false; 419 } 420 421 return true; 422 } 423 424 private String getRoot() 425 { 426 Token t = getFirstToken(); 427 428 434 435 436 437 int slashbang = t.image.indexOf("\\!"); 438 439 if (slashbang != -1) 440 { 441 448 449 452 453 int i = 0; 454 int len = t.image.length(); 455 456 i = t.image.indexOf('$'); 457 458 if (i == -1) 459 { 460 461 rsvc.error("ASTReference.getRoot() : internal error : " 462 + "no $ found for slashbang."); 463 computableReference = false; 464 nullString = t.image; 465 return nullString; 466 } 467 468 while (i < len && t.image.charAt(i) != '\\') 469 { 470 i++; 471 } 472 473 474 475 int start = i; 476 int count = 0; 477 478 while (i < len && t.image.charAt(i++) == '\\') 479 { 480 count++; 481 } 482 483 487 488 nullString = t.image.substring(0,start); nullString += t.image.substring(start, start + count-1 ); nullString += t.image.substring(start+count); 492 496 497 computableReference = false; 498 499 return nullString; 500 } 501 502 508 509 escaped = false; 510 511 if (t.image.startsWith("\\")) 512 { 513 516 517 int i = 0; 518 int len = t.image.length(); 519 520 while (i < len && t.image.charAt(i) == '\\') 521 { 522 i++; 523 } 524 525 if ((i % 2) != 0) 526 escaped = true; 527 528 if (i > 0) 529 escPrefix = t.image.substring(0, i / 2 ); 530 531 t.image = t.image.substring(i); 532 } 533 534 539 540 int loc1 = t.image.lastIndexOf('$'); 541 542 547 if (loc1 > 0) 548 { 549 morePrefix = morePrefix + t.image.substring(0, loc1); 550 t.image = t.image.substring(loc1); 551 } 552 553 558 559 nullString = literal(); 560 561 if (t.image.startsWith("$!")) 562 { 563 referenceType = QUIET_REFERENCE; 564 565 568 569 if (!escaped) 570 nullString = ""; 571 572 if (t.image.startsWith("$!{")) 573 { 574 577 578 return t.next.image; 579 } 580 else 581 { 582 585 586 return t.image.substring(2); 587 } 588 } 589 else if (t.image.equals("${")) 590 { 591 594 595 referenceType = FORMAL_REFERENCE; 596 return t.next.image; 597 } 598 else if (t.image.startsWith("$")) 599 { 600 604 605 referenceType = NORMAL_REFERENCE; 606 return t.image.substring(1); 607 } 608 else 609 { 610 615 referenceType = RUNT; 616 return t.image; 617 } 618 619 } 620 621 public Object getVariableValue(Context context, String variable) 622 { 623 return context.get(variable); 624 } 625 626 627 639 public void setLiteral(String literal) 640 { 641 644 645 if( this.literal == null) 646 this.literal = literal; 647 } 648 649 655 public String literal() 656 { 657 if (literal != null) 658 return literal; 659 660 return super.literal(); 661 } 662 } 663 | Popular Tags |