001 package railo.transformer.bytecode.util; 002 003 import java.util.HashMap; 004 import java.util.Map; 005 006 import org.objectweb.asm.Opcodes; 007 import org.objectweb.asm.Type; 008 import org.objectweb.asm.commons.GeneratorAdapter; 009 import org.objectweb.asm.commons.Method; 010 011 import railo.commons.lang.CFTypes; 012 import railo.commons.lang.StringUtil; 013 import railo.runtime.op.Caster; 014 import railo.transformer.bytecode.BytecodeContext; 015 import railo.transformer.bytecode.BytecodeException; 016 import railo.transformer.bytecode.Position; 017 import railo.transformer.bytecode.Statement; 018 import railo.transformer.bytecode.expression.ExprString; 019 import railo.transformer.bytecode.expression.Expression; 020 import railo.transformer.bytecode.literal.LitString; 021 022 public final class ExpressionUtil { 023 024 public static final Method START = new Method( 025 "exeLogStart", 026 Types.VOID, 027 new Type[]{Types.INT_VALUE,Types.STRING}); 028 public static final Method END = new Method( 029 "exeLogEnd", 030 Types.VOID, 031 new Type[]{Types.INT_VALUE,Types.STRING}); 032 033 034 private static Map<String,String> last=new HashMap<String,String>(); 035 036 public static void writeOutExpressionArray(BytecodeContext bc, Type arrayType, Expression[] array) throws BytecodeException { 037 GeneratorAdapter adapter = bc.getAdapter(); 038 adapter.push(array.length); 039 adapter.newArray(arrayType); 040 for (int i = 0; i < array.length; i++) { 041 adapter.dup(); 042 adapter.push(i); 043 array[i].writeOut(bc, Expression.MODE_REF); 044 adapter.visitInsn(Opcodes.AASTORE); 045 } 046 } 047 048 /** 049 * visit line number 050 * @param adapter 051 * @param line 052 * @param silent id silent this is ignored for log 053 */ 054 public static synchronized void visitLine(BytecodeContext bc, Position pos) { 055 if(pos!=null){ 056 visitLine(bc, pos.line); 057 } 058 } 059 private static synchronized void visitLine(BytecodeContext bc, int line) { 060 if(line>0){ 061 if(!(""+line).equals(last.get(bc.getClassName()+":"+bc.getId()))){ 062 //writeLog(bc,line); 063 bc.visitLineNumber(line); 064 last.put(bc.getClassName()+":"+bc.getId(),""+line); 065 last.put(bc.getClassName(),""+line); 066 } 067 } 068 } 069 070 public static synchronized void lastLine(BytecodeContext bc) { 071 int line = Caster.toIntValue(last.get(bc.getClassName()),-1); 072 visitLine(bc, line); 073 } 074 075 /** 076 * write out expression without LNT 077 * @param value 078 * @param bc 079 * @param mode 080 * @throws BytecodeException 081 */ 082 public static void writeOutSilent(Expression value, BytecodeContext bc, int mode) throws BytecodeException { 083 Position start = value.getStart(); 084 Position end = value.getEnd(); 085 value.setStart(null); 086 value.setEnd(null); 087 value.writeOut(bc, mode); 088 value.setStart(start); 089 value.setEnd(end); 090 } 091 public static void writeOut(Expression value, BytecodeContext bc, int mode) throws BytecodeException { 092 value.writeOut(bc, mode); 093 } 094 095 public static short toShortType(ExprString expr,boolean alsoAlias, short defaultValue) { 096 if(expr instanceof LitString){ 097 return CFTypes.toShort(((LitString)expr).getString(),alsoAlias,defaultValue); 098 } 099 return defaultValue; 100 } 101 102 public static void callStartLog(BytecodeContext bc, Statement s, String id) { 103 call_Log(bc, START, s.getStart(),id); 104 } 105 public static void callEndLog(BytecodeContext bc, Statement s, String id) { 106 call_Log(bc, END, s.getEnd(),id); 107 } 108 109 private static void call_Log(BytecodeContext bc, Method method, Position pos, String id) { 110 if(!bc.writeLog() || pos==null || (StringUtil.indexOfIgnoreCase(bc.getMethod().getName(),"call")==-1))return; 111 try{ 112 GeneratorAdapter adapter = bc.getAdapter(); 113 adapter.loadArg(0); 114 //adapter.checkCast(Types.PAGE_CONTEXT_IMPL); 115 adapter.push(pos.pos); 116 adapter.push(id); 117 adapter.invokeVirtual(Types.PAGE_CONTEXT, method); 118 } 119 catch(Throwable t) { 120 t.printStackTrace(); 121 } 122 } 123 124 public static boolean doLog(BytecodeContext bc) { 125 return bc.writeLog() && StringUtil.indexOfIgnoreCase(bc.getMethod().getName(),"call")!=-1; 126 } 127 }