001 package railo.transformer.bytecode.cast; 002 003 import org.objectweb.asm.Type; 004 import org.objectweb.asm.commons.GeneratorAdapter; 005 import org.objectweb.asm.commons.Method; 006 007 import railo.commons.lang.ClassException; 008 import railo.commons.lang.ClassUtil; 009 import railo.commons.lang.StringUtil; 010 import railo.transformer.bytecode.BytecodeContext; 011 import railo.transformer.bytecode.BytecodeException; 012 import railo.transformer.bytecode.expression.Expression; 013 import railo.transformer.bytecode.expression.ExpressionBase; 014 import railo.transformer.bytecode.expression.var.Variable; 015 import railo.transformer.bytecode.expression.var.VariableString; 016 import railo.transformer.bytecode.util.Methods_Caster; 017 import railo.transformer.bytecode.util.Types; 018 019 /** 020 * cast a Expression to a Double 021 */ 022 public final class CastOther extends ExpressionBase implements Cast { 023 // TODO support short type 024 private Expression expr; 025 private String type; 026 private String lcType; 027 028 private CastOther(Expression expr, String type, String lcType) { 029 super(expr.getStart(),expr.getEnd()); 030 this.expr=expr; 031 this.type=type; 032 this.lcType=lcType; 033 034 } 035 036 public static Expression toExpression(Expression expr, String type) { 037 if(type==null) return expr; 038 039 String lcType=StringUtil.toLowerCase(type); 040 switch(lcType.charAt(0)) { 041 case 'a': 042 if("any".equals(lcType)) { 043 return expr; 044 } 045 break; 046 case 'b': 047 if("boolean".equals(type) || "bool".equals(lcType)) return CastBoolean.toExprBoolean(expr); 048 break; 049 case 'd': 050 if("double".equals(type)) return CastDouble.toExprDouble(expr); 051 break; 052 case 'i': 053 if("int".equals(lcType)) return CastInt.toExprInt(expr); 054 case 'n': 055 if("number".equals(lcType) || "numeric".equals(lcType))return CastDouble.toExprDouble(expr); 056 break; 057 case 'o': 058 if("object".equals(lcType)) { 059 return expr; 060 } 061 break; 062 case 's': 063 if("string".equals(lcType)) return CastString.toExprString(expr); 064 //if("string_array".equals(lcType)) return StringArray.toExpr(expr); 065 break; 066 case 'u': 067 if("uuid".equals(lcType)) return CastString.toExprString(expr); 068 break; 069 case 'v': 070 if("variablename".equals(lcType)) return VariableString.toExprString(expr); 071 if("variable_name".equals(lcType)) return VariableString.toExprString(expr); 072 if("variablestring".equals(lcType)) return VariableString.toExprString(expr); 073 if("variable_string".equals(lcType)) return VariableString.toExprString(expr); 074 if("void".equals(lcType)) return expr; 075 break; 076 077 078 079 080 } 081 return new CastOther(expr,type,lcType); 082 } 083 084 // Array toArray(Object) 085 final public static Method TO_ARRAY = new Method("toArray", 086 Types.ARRAY, 087 new Type[]{Types.OBJECT}); 088 089 // String toBase64 (Object); 090 final public static Method TO_BASE64 = new Method("toBase64", 091 Types.STRING, 092 new Type[]{Types.OBJECT}); 093 094 // byte[] toBinary (Object) 095 final public static Method TO_BINARY = new Method("toBinary", 096 Types.BYTE_VALUE_ARRAY, 097 new Type[]{Types.OBJECT}); 098 099 // byte[] toCollection (Object) 100 final public static Method TO_COLLECTION = new Method("toCollection", 101 Types.BYTE_VALUE_ARRAY, 102 new Type[]{Types.OBJECT}); 103 104 // railo.runtime.Component toComponent (Object) 105 final public static Method TO_COMPONENT = new Method("toComponent", 106 Types.COMPONENT, 107 new Type[]{Types.OBJECT}); 108 109 110 // String toDecimal (Object) 111 final public static Method TO_DECIMAL = new Method("toDecimal", 112 Types.STRING, 113 new Type[]{Types.OBJECT}); 114 115 // railo.runtime.config.Config getConfig () 116 final public static Method GET_CONFIG = new Method("getConfig", 117 Types.CONFIG_WEB, 118 new Type[]{}); 119 120 //java.util.TimeZone getTimeZone () 121 final public static Method GET_TIMEZONE = new Method("getTimeZone", 122 Types.TIMEZONE, 123 new Type[]{}); 124 125 // Excel toExcel (Object) 126 final public static Method TO_EXCEL = new Method("toExcel", 127 Types.EXCEL, 128 new Type[]{Types.OBJECT}); 129 130 /** 131 * @see railo.transformer.bytecode.expression.Expression#_writeOut(org.objectweb.asm.commons.GeneratorAdapter, int) 132 */ 133 public Type _writeOut(BytecodeContext bc, int mode) throws BytecodeException { 134 //Caster.toDecimal(null); 135 GeneratorAdapter adapter = bc.getAdapter(); 136 char first=lcType.charAt(0); 137 Type rtn; 138 139 switch(first) { 140 case 'a': 141 if("array".equals(lcType)) { 142 rtn=expr.writeOut(bc,MODE_REF); 143 if(!rtn.equals(Types.ARRAY)) 144 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_ARRAY); 145 return Types.ARRAY; 146 } 147 break; 148 case 'b': 149 if("base64".equals(lcType)) { 150 expr.writeOut(bc,MODE_REF); 151 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BASE64); 152 return Types.STRING; 153 } 154 if("binary".equals(lcType)) { 155 rtn=expr.writeOut(bc,MODE_REF); 156 if(!rtn.equals(Types.BYTE_VALUE_ARRAY)) 157 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BINARY); 158 return Types.BYTE_VALUE_ARRAY; 159 } 160 if("byte".equals(type)) { 161 rtn=expr.writeOut(bc,MODE_VALUE); 162 if(!rtn.equals(Types.BYTE_VALUE)) 163 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE_VALUE[Types.getType(rtn)]); 164 return Types.BYTE_VALUE; 165 } 166 if("byte".equals(lcType)) { 167 rtn=expr.writeOut(bc,MODE_REF); 168 if(!rtn.equals(Types.BYTE)) 169 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE[Types.getType(rtn)]); 170 return Types.BYTE; 171 } 172 if("boolean".equals(lcType)) { 173 return CastBoolean.toExprBoolean(expr).writeOut(bc, MODE_REF); 174 } 175 break; 176 case 'c': 177 if("char".equals(lcType)) { 178 rtn=expr.writeOut(bc,MODE_VALUE); 179 if(!rtn.equals(Types.CHAR)) 180 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHAR_VALUE[Types.getType(rtn)]); 181 return Types.CHAR; 182 } 183 if("character".equals(lcType)) { 184 rtn=expr.writeOut(bc,MODE_REF); 185 if(!rtn.equals(Types.CHARACTER)) 186 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHARACTER[Types.getType(rtn)]); 187 return Types.CHARACTER; 188 } 189 if("collection".equals(lcType)) { 190 rtn=expr.writeOut(bc,MODE_REF); 191 if(!rtn.equals(Types.COLLECTION)) 192 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COLLECTION); 193 return Types.COLLECTION; 194 } 195 if("component".equals(lcType)) { 196 rtn=expr.writeOut(bc,MODE_REF); 197 if(!rtn.equals(Types.COMPONENT)) 198 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_COMPONENT); 199 return Types.COMPONENT; 200 } 201 break; 202 case 'd': 203 if("double".equals(lcType)) { 204 return CastDouble.toExprDouble(expr).writeOut(bc, MODE_REF); 205 } 206 if("date".equals(lcType) || "datetime".equals(lcType)) { 207 // First Arg 208 rtn=expr.writeOut(bc,MODE_REF); 209 if(rtn.equals(Types.DATE_TIME)) return Types.DATE_TIME; 210 211 int type=Types.getType(rtn); 212 213 // Second Arg 214 adapter.loadArg(0); 215 adapter.invokeVirtual(Types.PAGE_CONTEXT,GET_CONFIG); 216 adapter.invokeInterface(Types.CONFIG_WEB,GET_TIMEZONE); 217 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DATE[type]); 218 return Types.DATE_TIME; 219 } 220 if("decimal".equals(lcType)) { 221 rtn=expr.writeOut(bc,MODE_REF); 222 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DECIMAL[Types.getType(rtn)]); 223 return Types.STRING; 224 } 225 break; 226 case 'e': 227 if("excel".equals(type)) { 228 expr.writeOut(bc,MODE_REF); 229 adapter.invokeStatic(Types.EXCEL_UTIL,TO_EXCEL); 230 return Types.EXCEL; 231 } 232 break; 233 case 'f': 234 if("file".equals(lcType)) { 235 rtn=expr.writeOut(bc,MODE_REF); 236 if(!rtn.equals(Types.FILE)) 237 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FILE); 238 return Types.FILE; 239 } 240 if("float".equals(type)) { 241 rtn=expr.writeOut(bc,MODE_VALUE); 242 if(!rtn.equals(Types.FLOAT_VALUE)) 243 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT_VALUE[Types.getType(rtn)]); 244 return Types.FLOAT_VALUE; 245 } 246 if("float".equals(lcType)) { 247 rtn=expr.writeOut(bc,MODE_REF); 248 if(!rtn.equals(Types.FLOAT)) 249 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT[Types.getType(rtn)]); 250 return Types.FLOAT; 251 } 252 break; 253 case 'i': 254 if("int".equals(lcType)) { 255 rtn=expr.writeOut(bc,MODE_VALUE); 256 if(!rtn.equals(Types.INT_VALUE)) 257 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INT_VALUE[Types.getType(rtn)]); 258 return Types.INT_VALUE; 259 } 260 if("integer".equals(lcType)) { 261 rtn=expr.writeOut(bc,MODE_REF); 262 if(!rtn.equals(Types.INTEGER)) 263 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INTEGER[Types.getType(rtn)]); 264 return Types.INTEGER; 265 } 266 break; 267 case 'j': 268 269 if("java.lang.boolean".equals(lcType)) { 270 return CastBoolean.toExprBoolean(expr).writeOut(bc, MODE_REF); 271 } 272 if("java.lang.double".equals(lcType)) { 273 return CastDouble.toExprDouble(expr).writeOut(bc, MODE_REF); 274 } 275 if("java.lang.string".equals(lcType)) { 276 return CastString.toExprString(expr).writeOut(bc, MODE_REF); 277 } 278 if("java.lang.stringbuffer".equals(lcType)) { 279 rtn=expr.writeOut(bc,MODE_REF); 280 if(!rtn.equals(Types.STRING_BUFFER)) 281 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRING_BUFFER); 282 return Types.STRING_BUFFER; 283 } 284 if("java.lang.byte".equals(lcType)) { 285 rtn=expr.writeOut(bc,MODE_REF); 286 if(!rtn.equals(Types.BYTE)) 287 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_BYTE[Types.getType(rtn)]); 288 return Types.BYTE; 289 } 290 if("java.lang.character".equals(lcType)) { 291 rtn=expr.writeOut(bc,MODE_REF); 292 if(!rtn.equals(Types.CHARACTER)) 293 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_CHARACTER[Types.getType(rtn)]); 294 return Types.CHARACTER; 295 } 296 if("java.lang.short".equals(lcType)) { 297 rtn=expr.writeOut(bc,MODE_REF); 298 if(!rtn.equals(Types.SHORT)) 299 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT[Types.getType(rtn)]); 300 return Types.SHORT; 301 } 302 if("java.lang.integer".equals(lcType)) { 303 rtn=expr.writeOut(bc,MODE_REF); 304 if(!rtn.equals(Types.INTEGER)) 305 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_INTEGER[Types.getType(rtn)]); 306 return Types.INTEGER; 307 } 308 if("java.lang.long".equals(lcType)) { 309 rtn=expr.writeOut(bc,MODE_REF); 310 if(!rtn.equals(Types.LONG)) 311 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG[Types.getType(rtn)]); 312 return Types.LONG; 313 } 314 if("java.lang.float".equals(lcType)) { 315 rtn=expr.writeOut(bc,MODE_REF); 316 if(!rtn.equals(Types.FLOAT)) 317 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FLOAT[Types.getType(rtn)]); 318 return Types.FLOAT; 319 } 320 if("java.io.file".equals(lcType)) { 321 rtn=expr.writeOut(bc,MODE_REF); 322 if(!rtn.equals(Types.FILE)) 323 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_FILE); 324 return Types.FILE; 325 } 326 if("java.lang.object".equals(lcType)) { 327 return expr.writeOut(bc,MODE_REF); 328 } 329 else if("java.util.date".equals(lcType)) { 330 // First Arg 331 rtn=expr.writeOut(bc,MODE_REF); 332 if(rtn.equals(Types.DATE)) return Types.DATE; 333 if(rtn.equals(Types.DATE_TIME)) return Types.DATE_TIME; 334 335 // Second Arg 336 adapter.loadArg(0); 337 adapter.invokeVirtual(Types.PAGE_CONTEXT,GET_CONFIG); 338 adapter.invokeVirtual(Types.CONFIG_WEB,GET_TIMEZONE); 339 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_DATE[Types.getType(rtn)]); 340 return Types.DATE_TIME; 341 } 342 break; 343 case 'l': 344 if("long".equals(type)) { 345 rtn=expr.writeOut(bc,MODE_VALUE); 346 if(!rtn.equals(Types.LONG_VALUE)) 347 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG_VALUE[Types.getType(rtn)]); 348 return Types.LONG_VALUE; 349 } 350 else if("long".equals(lcType)) { 351 rtn=expr.writeOut(bc,MODE_REF); 352 if(!rtn.equals(Types.LONG)) 353 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_LONG[Types.getType(rtn)]); 354 return Types.LONG; 355 } 356 break; 357 case 'n': 358 if("node".equals(lcType)) { 359 rtn=expr.writeOut(bc,MODE_REF); 360 if(!rtn.equals(Types.NODE)) 361 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NODE); 362 return Types.NODE; 363 } 364 else if("null".equals(lcType)) { 365 expr.writeOut(bc,MODE_REF); 366 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NULL); 367 // TODO gibt es einen null typ? 368 return Types.OBJECT; 369 } 370 break; 371 case 'o': 372 if("object".equals(lcType) || "other".equals(lcType)) { 373 expr.writeOut(bc,MODE_REF); 374 return Types.OBJECT; 375 } 376 break; 377 case 's': 378 if("struct".equals(lcType)) { 379 rtn=expr.writeOut(bc,MODE_REF); 380 if(!rtn.equals(Types.STRUCT)) 381 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRUCT); 382 return Types.STRUCT; 383 } 384 if("short".equals(type)) { 385 rtn=expr.writeOut(bc,MODE_VALUE); 386 if(!rtn.equals(Types.SHORT_VALUE)) 387 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT_VALUE[Types.getType(rtn)]); 388 return Types.SHORT_VALUE; 389 } 390 if("short".equals(lcType)) { 391 rtn=expr.writeOut(bc,MODE_REF); 392 if(!rtn.equals(Types.SHORT)) 393 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_SHORT[Types.getType(rtn)]); 394 return Types.SHORT; 395 } 396 if("stringbuffer".equals(lcType)) { 397 rtn=expr.writeOut(bc,MODE_REF); 398 if(!rtn.equals(Types.STRING_BUFFER)) 399 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_STRING_BUFFER); 400 return Types.STRING_BUFFER; 401 } 402 break; 403 404 case 'x': 405 if("xml".equals(lcType)) { 406 rtn=expr.writeOut(bc,MODE_REF); 407 if(!rtn.equals(Types.NODE)) 408 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_NODE); 409 return Types.NODE; 410 } 411 break; 412 default: 413 if("query".equals(lcType)) { 414 rtn=expr.writeOut(bc,MODE_REF); 415 if(!rtn.equals(Types.QUERY)) 416 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_QUERY); 417 return Types.QUERY; 418 } 419 if("querycolumn".equals(lcType)) { 420 rtn=(expr instanceof Variable)?((Variable)expr).writeOutCollection(bc, mode):expr.writeOut(bc,MODE_REF); 421 if(!rtn.equals(Types.QUERY_COLUMN)) { 422 423 adapter.loadArg(0); 424 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_QUERY_COLUMN); 425 } 426 return Types.QUERY_COLUMN; 427 } 428 else if("timespan".equals(lcType)) { 429 rtn=expr.writeOut(bc,MODE_REF); 430 if(!rtn.equals(Types.TIMESPAN)) 431 adapter.invokeStatic(Types.CASTER,Methods_Caster.TO_TIMESPAN); 432 return Types.TIMESPAN; 433 } 434 } 435 Type t=getType(type); 436 437 expr.writeOut(bc,MODE_REF); 438 adapter.checkCast(t); 439 return t; 440 } 441 442 /* 443 private int writeExprx(BytecodeContext bc) throws TemplateException { 444 return Types.getType(expr.writeOut(bc,MODE_VALUE)); 445 }*/ 446 447 448 449 public static Type getType(String type) throws BytecodeException { 450 if(StringUtil.isEmpty(type)) return Types.OBJECT; 451 452 453 String lcType=StringUtil.toLowerCase(type); 454 switch(lcType.charAt(0)) { 455 case 'a': 456 if("any".equals(lcType)) return Types.OBJECT; 457 if("array".equals(lcType)) return Types.ARRAY; 458 break; 459 case 'b': 460 if("bool".equals(lcType) || "boolean".equals(type)) return Types.BOOLEAN_VALUE; 461 if("boolean".equals(lcType)) return Types.BOOLEAN; 462 if("base64".equals(lcType)) return Types.STRING; 463 464 if("binary".equals(lcType)) return Types.BYTE_VALUE_ARRAY; 465 if("byte".equals(type)) return Types.BYTE_VALUE; 466 if("byte".equals(lcType)) return Types.BYTE; 467 468 break; 469 470 case 'c': 471 if("char".equals(lcType)) return Types.CHAR; 472 if("character".equals(lcType)) return Types.CHARACTER; 473 if("collection".equals(lcType)) return Types.COLLECTION; 474 if("component".equals(lcType)) return Types.COMPONENT; 475 break; 476 477 case 'd': 478 if("double".equals(type)) return Types.DOUBLE_VALUE; 479 if("double".equals(lcType)) return Types.DOUBLE; 480 481 if("date".equals(lcType) || "datetime".equals(lcType))return Types.DATE_TIME; 482 if("decimal".equals(lcType)) return Types.STRING; 483 484 break; 485 486 case 'e': 487 if("excel".equals(lcType)) return Types.EXCEL; 488 break; 489 case 'f': 490 if("file".equals(lcType)) return Types.FILE; 491 if("float".equals(type)) return Types.FLOAT_VALUE; 492 if("float".equals(lcType)) return Types.FLOAT; 493 if("function".equals(lcType)) return Types.UDF; 494 break; 495 496 case 'i': 497 if("int".equals(lcType)) return Types.INT_VALUE; 498 if("integer".equals(lcType)) return Types.INTEGER; 499 break; 500 501 case 'l': 502 if("long".equals(type)) return Types.LONG_VALUE; 503 if("long".equals(lcType)) return Types.LONG; 504 break; 505 case 'n': 506 if("node".equals(lcType)) return Types.NODE; 507 if("null".equals(lcType)) return Types.OBJECT; 508 if("number".equals(lcType)) return Types.DOUBLE_VALUE; 509 if("numeric".equals(lcType)) return Types.DOUBLE_VALUE; 510 break; 511 case 's': 512 if("string".equals(lcType)) return Types.STRING; 513 if("struct".equals(lcType)) return Types.STRUCT; 514 if("short".equals(type)) return Types.SHORT_VALUE; 515 if("short".equals(lcType)) return Types.SHORT; 516 break; 517 case 'o': 518 if("other".equals(lcType)) return Types.OBJECT; 519 if("object".equals(lcType)) return Types.OBJECT; 520 break; 521 case 'u': 522 if("uuid".equals(lcType)) return Types.STRING; 523 if("udf".equals(lcType)) return Types.UDF; 524 break; 525 case 'q': 526 if("query".equals(lcType)) return Types.QUERY; 527 if("querycolumn".equals(lcType)) return Types.QUERY_COLUMN; 528 break; 529 case 't': 530 if("timespan".equals(lcType)) return Types.TIMESPAN; 531 break; 532 case 'v': 533 if("variablename".equals(lcType)) return Types.STRING; 534 if("variable_name".equals(lcType)) return Types.STRING; 535 if("variablestring".equals(lcType)) return Types.STRING; 536 if("variable_string".equals(lcType)) return Types.STRING; 537 if("void".equals(lcType)) return Types.VOID; 538 break; 539 case 'x': 540 if("xml".equals(lcType)) return Types.NODE; 541 break; 542 } 543 try { 544 return Type.getType(ClassUtil.loadClass(type)); 545 } 546 catch (ClassException e) { 547 throw new BytecodeException(e.getMessage(),null); 548 } 549 550 } 551 552 @Override 553 public Expression getExpr() { 554 return expr; 555 } 556 557 /** 558 * @return the type 559 */ 560 public String getType() { 561 return type; 562 } 563 564 } 565 566 567 568