| 1 29 30 package com.caucho.el; 31 32 import com.caucho.config.types.Period; 33 import com.caucho.util.BeanUtil; 34 import com.caucho.util.IntMap; 35 import com.caucho.util.L10N; 36 import com.caucho.vfs.ReadStream; 37 import com.caucho.vfs.WriteStream; 38 39 import javax.el.ELContext; 40 import javax.el.ELException; 41 import javax.el.MethodInfo; 42 import javax.el.PropertyNotFoundException; 43 import javax.el.PropertyNotWritableException; 44 import javax.el.ValueExpression; 45 import javax.servlet.jsp.JspWriter ; 46 import java.io.IOException ; 47 import java.io.Reader ; 48 import java.io.Writer ; 49 import java.lang.reflect.InvocationTargetException ; 50 import java.lang.reflect.Method ; 51 import java.math.BigDecimal ; 52 import java.math.BigInteger ; 53 import java.util.HashMap ; 54 import java.util.Map ; 55 import java.util.logging.Level ; 56 import java.util.logging.Logger ; 57 58 61 public abstract class Expr extends ValueExpression { 62 protected static final Logger log 63 = Logger.getLogger(Expr.class.getName()); 64 protected static final L10N L = new L10N(Expr.class); 65 66 private static final Character NULL_CHAR 67 = new Character ((char) 0); 68 69 private static final long DAY = 24L * 3600L * 1000L; 70 71 private static final BigDecimal BIG_DECIMAL_ZERO = new BigDecimal ("0"); 72 73 private static final BigInteger BIG_INTEGER_ZERO = new BigInteger ("0"); 74 75 private static final HashMap <Class ,CoerceType> _coerceMap 76 = new HashMap <Class ,CoerceType>(); 77 78 final static int ADD = 1; 80 final static int SUB = ADD + 1; 81 final static int MUL = SUB + 1; 82 final static int DIV = MUL + 1; 83 final static int MOD = DIV + 1; 84 final static int EQ = MOD + 1; 85 final static int NE = EQ + 1; 86 final static int LT = NE + 1; 87 final static int LE = LT + 1; 88 final static int GT = LE + 1; 89 final static int GE = GT + 1; 90 final static int AND = GE + 1; 91 final static int OR = AND + 1; 92 93 final static int NOT = OR + 1; 94 final static int MINUS = NOT + 1; 95 final static int EMPTY = MINUS + 1; 96 97 final static int OBJECT = 0; 98 final static int BOOLEAN = OBJECT + 1; 99 final static int BYTE = BOOLEAN + 1; 100 final static int SHORT = BYTE + 1; 101 final static int INT = SHORT + 1; 102 final static int LONG = INT + 1; 103 final static int FLOAT = LONG + 1; 104 final static int DOUBLE = FLOAT + 1; 105 106 final static int BOOLEAN_OBJ = DOUBLE + 1; 107 final static int BYTE_OBJ = BOOLEAN_OBJ + 1; 108 final static int SHORT_OBJ = BYTE_OBJ + 1; 109 final static int INT_OBJ = SHORT_OBJ + 1; 110 final static int LONG_OBJ = INT_OBJ + 1; 111 final static int FLOAT_OBJ = LONG_OBJ + 1; 112 final static int DOUBLE_OBJ = FLOAT_OBJ + 1; 113 114 final static int STRING = DOUBLE_OBJ + 1; 115 116 final static IntMap _typeMap = new IntMap(); 117 118 121 public boolean isConstant() 122 { 123 return false; 124 } 125 126 129 public boolean isReadOnly(ELContext env) 130 { 131 return true; 132 } 133 134 137 public boolean isLiteralText() 138 { 139 return false; 140 } 141 142 147 public Expr createField(Expr field) 148 { 149 return new ArrayResolverExpr(this, field); 150 } 151 152 157 public Expr createField(String field) 158 { 159 return createField(new StringLiteral(field)); 160 } 161 162 168 public Expr createMethod(Expr []args) 169 { 170 return new FunctionExpr(this, args); 171 } 172 173 180 abstract public Object getValue(ELContext env) 181 throws ELException; 182 183 190 public MethodInfo getMethodInfo(ELContext env, 191 Class <?> returnType, 192 Class <?> []argTypes) 193 throws ELException 194 { 195 throw new ELException(L.l("'{0}' is an illegal method expression." + getClass(), 196 toString())); 197 } 198 199 206 public Object invoke(ELContext env, Class <?> []argTypes, Object []args) 207 throws ELException 208 { 209 throw new ELException(L.l("'{0}' is an illegal method expression." + getClass(), 210 toString())); 211 } 212 213 220 public final Object evalObject(ELContext env) 221 throws ELException 222 { 223 return getValue(env); 224 } 225 226 233 public boolean evalBoolean(ELContext env) 234 throws ELException 235 { 236 return toBoolean(getValue(env), env); 237 } 238 239 246 public double evalDouble(ELContext env) 247 throws ELException 248 { 249 return toDouble(getValue(env), env); 250 } 251 252 259 public long evalLong(ELContext env) 260 throws ELException 261 { 262 return toLong(getValue(env), env); 263 } 264 265 272 public String evalString(ELContext env) 273 throws ELException 274 { 275 return toString(getValue(env), env); 276 } 277 278 285 public String evalStringWithNull(ELContext env) 286 throws ELException 287 { 288 return toStringWithNull(getValue(env), env); 289 } 290 291 298 public char evalCharacter(ELContext env) 299 throws ELException 300 { 301 return toCharacter(getValue(env), env); 302 } 303 304 311 public long evalPeriod(ELContext env) 312 throws ELException 313 { 314 try { 315 Object obj = getValue(env); 316 317 if (obj instanceof Number ) 318 return 1000L * ((Number ) obj).longValue(); 319 else 320 return Period.toPeriod(toString(obj, env)); 321 } catch (Exception e) { 322 throw new ELException(e.getMessage()); 323 } 324 325 } 326 327 334 public BigInteger evalBigInteger(ELContext env) 335 throws ELException 336 { 337 return toBigInteger(getValue(env), env); 338 } 339 340 347 public BigDecimal evalBigDecimal(ELContext env) 348 throws ELException 349 { 350 return toBigDecimal(getValue(env), env); 351 } 352 353 360 @Override  361 public void setValue(ELContext env, Object value) 362 throws PropertyNotFoundException, 363 PropertyNotWritableException, 364 ELException 365 { 366 throw new PropertyNotWritableException(getClass().getName() + ": " + toString()); 367 } 368 369 379 public boolean print(WriteStream out, 380 ELContext env, 381 boolean escapeXml) 382 throws IOException , ELException 383 { 384 Object obj = getValue(env); 385 386 if (obj == null) 387 return true; 388 else if (escapeXml) { 389 toStreamEscaped(out, obj); 390 return false; 391 } 392 else { 393 toStream(out, obj); 394 return false; 395 } 396 } 397 398 408 public boolean print(JspWriter out, 409 ELContext env, 410 boolean escapeXml) 411 throws IOException , ELException 412 { 413 Object obj = getValue(env); 414 415 if (obj == null) 416 return true; 417 else if (escapeXml) { 418 toStreamEscaped(out, obj); 419 return false; 420 } 421 else { 422 toStream(out, obj); 423 return false; 424 } 425 } 426 427 432 public void printCreate(WriteStream os) 433 throws IOException  434 { 435 throw new UnsupportedOperationException (getClass().getName()); 436 } 437 438 442 @Override  443 public String getExpressionString() 444 { 445 return toString(); 446 } 447 448 @Override  449 public Class <?> getExpectedType() 450 { 451 return Object .class; 452 } 453 454 @Override  455 public Class <?> getType(ELContext context) 456 throws PropertyNotFoundException, 457 ELException 458 { 459 Object value = getValue(context); 460 461 if (value == null) 462 return null; 463 else 464 return value.getClass(); 465 } 466 467 471 474 public static boolean isDouble(Object o) 475 { 476 if (o instanceof Double ) 477 return true; 478 else if (o instanceof Float ) 479 return true; 480 else if (! (o instanceof String )) 481 return false; 482 else { 483 String s = (String ) o; 484 int len = s.length(); 485 486 for (int i = 0; i < len; i++) { 487 char ch = s.charAt(i); 488 489 if (ch == '.' || ch == 'e' || ch == 'E') 490 return true; 491 } 492 493 return false; 494 } 495 } 496 497 504 public static String toStringWithNull(Object value, ELContext env) 505 { 506 if (value == null || value instanceof String ) 507 return (String ) value; 508 else 509 return value.toString(); 510 } 511 512 519 public static String toString(Object value, ELContext env) 520 { 521 if (value == null) 522 return ""; 523 else if (value instanceof String ) 524 return (String ) value; 525 else 526 return value.toString(); 527 } 528 529 536 public static String toString(long value, ELContext env) 537 { 538 return String.valueOf(value); 539 } 540 541 548 public static String toString(double value, ELContext env) 549 { 550 return String.valueOf(value); 551 } 552 553 560 public static String toString(boolean value, ELContext env) 561 { 562 return String.valueOf(value); 563 } 564 565 572 public static String toString(char value, ELContext env) 573 { 574 return String.valueOf(value); 575 } 576 577 584 public static char toCharacter(Object value, ELContext env) 585 throws ELException 586 { 587 if (value == null) 588 return (char) 0; 589 else if (value instanceof Character ) { 590 return ((Character ) value).charValue(); 591 } 592 else if (value instanceof String ) { 593 String s = (String ) value; 594 595 if (s == null || s.length() == 0) 596 return (char) 0; 597 else 598 return s.charAt(0); 599 } 600 else if (value instanceof Number ) { 601 Number number = (Number ) value; 602 603 return (char) number.intValue(); 604 } 605 else if (value instanceof Boolean ) { 606 ELException e = new ELException(L.l("can't convert {0} to character.", 607 value.getClass().getName())); 608 609 throw e; 610 615 } 616 else 617 return (char) toLong(value, env); 618 } 619 620 627 public static boolean toBoolean(Object value, ELContext env) 628 throws ELException 629 { 630 if (value == null || value.equals("")) 631 return false; 632 else if (value instanceof Boolean ) 633 return ((Boolean ) value).booleanValue(); 634 else if (value instanceof String ) 635 return value.equals("true") || value.equals("yes"); 636 else { 637 ELException e = new ELException(L.l("can't convert {0} to boolean.", 638 value.getClass().getName())); 639 640 throw e; 642 647 } 648 } 649 650 657 public static double toDouble(Object value, ELContext env) 658 throws ELException 659 { 660 if (value == null) 661 return 0; 662 else if (value instanceof Number ) { 663 double dValue = ((Number ) value).doubleValue(); 664 665 if (Double.isNaN(dValue)) 666 return 0; 667 else 668 return dValue; 669 } 670 else if (value.equals("")) 671 return 0; 672 else if (value instanceof String ) { 673 double dValue = Double.parseDouble((String ) value); 674 675 if (Double.isNaN(dValue)) 676 return 0; 677 else 678 return dValue; 679 } 680 else if (value instanceof Character ) { 681 return ((Character ) value).charValue(); 683 } 684 else { 685 ELException e = new ELException(L.l("can't convert {0} to double.", 686 value.getClass().getName())); 687 688 690 692 throw e; 693 } 694 } 695 696 703 public static BigDecimal toBigDecimal(Object value, ELContext env) 704 throws ELException 705 { 706 if (value == null) 707 return BIG_DECIMAL_ZERO; 708 else if (value instanceof BigDecimal ) 709 return (BigDecimal ) value; 710 else if (value instanceof Number ) { 711 double dValue = ((Number ) value).doubleValue(); 712 713 return new BigDecimal (dValue); 714 } 715 else if (value.equals("")) 716 return BIG_DECIMAL_ZERO; 717 else if (value instanceof String ) { 718 return new BigDecimal ((String ) value); 719 } 720 else if (value instanceof Character ) { 721 return new BigDecimal (((Character ) value).charValue()); 722 } 723 else { 724 ELException e = new ELException(L.l("can't convert {0} to BigDecimal.", 725 value.getClass().getName())); 726 727 error(e, env); 728 729 return BIG_DECIMAL_ZERO; 730 } 731 } 732 733 740 public static BigInteger toBigInteger(Object value, ELContext env) 741 throws ELException 742 { 743 if (value == null) 744 return BIG_INTEGER_ZERO; 745 else if (value instanceof BigInteger ) 746 return (BigInteger ) value; 747 else if (value instanceof Number ) { 748 return new BigDecimal (value.toString()).toBigInteger(); 750 } 751 else if (value.equals("")) 752 return BIG_INTEGER_ZERO; 753 else if (value instanceof String ) { 754 return new BigInteger ((String ) value); 755 } 756 else if (value instanceof Character ) { 757 return new BigInteger (String.valueOf((int) ((Character ) value).charValue())); 758 } 759 else { 760 ELException e = new ELException(L.l("can't convert {0} to BigInteger.", 761 value.getClass().getName())); 762 763 error(e, env); 764 765 return BIG_INTEGER_ZERO; 766 } 767 } 768 769 776 public static long toLong(Object value, ELContext env) 777 throws ELException 778 { 779 if (value == null) 780 return 0; 781 else if (value instanceof Number ) 782 return ((Number ) value).longValue(); 783 else if (value.equals("")) 784 return 0; 785 else if (value instanceof String ) { 786 try { 787 return (long) Double.parseDouble((String ) value); 788 } catch (Exception e) { 789 throw new ELException(e); 790 } 791 } 792 else if (value instanceof Character ) { 793 return ((Character ) value).charValue(); 795 } 796 else { 797 ELException e = new ELException(L.l("can't convert {0} to long.", 798 value.getClass().getName())); 799 800 802 804 throw e; 805 } 806 } 807 808 816 public static boolean toStream(JspWriter out, 817 Object value, 818 boolean isEscaped) 819 throws IOException  820 { 821 if (value == null) 822 return true; 823 824 if (isEscaped) 825 toStreamEscaped(out, value); 826 else 827 toStream(out, value); 828 829 return false; 830 } 831 832 838 public static void toStream(WriteStream out, Object value) 839 throws IOException  840 { 841 if (value == null) 842 return; 843 else if (value instanceof String ) 844 out.print((String ) value); 845 else if (value instanceof Reader ) { 846 out.writeStream((Reader ) value); 847 } 848 else 849 out.print(value.toString()); 850 } 851 852 858 public static void toStream(JspWriter out, Object value) 859 throws IOException  860 { 861 if (value == null) 862 return; 863 else if (value instanceof String ) 864 out.print((String ) value); 865 else if (value instanceof Reader ) { 866 Reader reader = (Reader ) value; 867 int ch; 868 869 while ((ch = reader.read()) > 0) { 870 out.print((char) ch); 871 } 872 } 873 else 874 out.print(value.toString()); 875 } 876 877 884 public static void printEscapedString(WriteStream os, String string) 885 throws IOException  886 { 887 int length = string.length(); 888 for (int i = 0; i < length; i++) { 889 char ch = string.charAt(i); 890 891 switch (ch) { 892 case '\\': 893 os.print("\\\\"); 894 break; 895 case '\n': 896 os.print("\\n"); 897 break; 898 case '\r': 899 os.print("\\r"); 900 break; 901 case '\"': 902 os.print("\\\""); 903 break; 904 default: 905 os.print((char) ch); 906 break; 907 } 908 } 909 } 910 911 917 public static void toStreamEscaped(Writer out, Object value) 918 throws IOException  919 { 920 if (value == null) 921 return; 922 else |