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