/** * Copyright (c) 2014, the Railo Company Ltd. * Copyright (c) 2015, Lucee Assosication Switzerland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.transformer.bytecode; import java.util.Iterator; import java.util.List; import java.util.Stack; import lucee.commons.lang.StringUtil; import lucee.runtime.PageSource; import lucee.runtime.config.Config; import lucee.runtime.engine.ThreadLocalPageContext; import lucee.transformer.Context; import lucee.transformer.Factory; import lucee.transformer.bytecode.visitor.OnFinally; import lucee.transformer.expression.literal.LitString; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.commons.GeneratorAdapter; import org.objectweb.asm.commons.Method; public class BytecodeContext implements Context { private ClassWriter classWriter; private GeneratorAdapter adapter; private String className; private List<LitString> keys; private int count=0; private Method method; private boolean doSubFunctions=true; //private StaticConstrBytecodeContext staticConstr; private ConstrBytecodeContext constr; private final boolean suppressWSbeforeArg; private final boolean output; private Stack<OnFinally> insideFinallies=new Stack<OnFinally>(); Stack<OnFinally> tcf=new Stack<OnFinally>(); private int currentTag; private int line; private BytecodeContext root; private boolean writeLog; private int rtn=-1; private final boolean returnValue; private static long _id=0; private synchronized static String id() { if(_id<0)_id=0; return StringUtil.addZeros(++_id,4); } private String id=id(); private Page page; protected PageSource ps; public BytecodeContext(PageSource ps,ConstrBytecodeContext constr,Page page,List<LitString> keys,ClassWriter classWriter,String className, GeneratorAdapter adapter, Method method,boolean writeLog, boolean suppressWSbeforeArg, boolean output, boolean returnValue) { this.classWriter = classWriter; this.className = className; this.writeLog = writeLog; this.adapter = adapter; this.keys = keys; this.method=method; //this.staticConstr=statConstr; this.constr=constr; this.page=page; this.suppressWSbeforeArg=suppressWSbeforeArg; this.returnValue=returnValue; this.output=output; if(ps!=null)this.ps=ps; else if(constr!=null)this.ps=constr.ps; } public BytecodeContext(ConstrBytecodeContext constr,List<LitString> keys,BytecodeContext bc, GeneratorAdapter adapter,Method method) { this.classWriter = bc.getClassWriter(); this.className = bc.getClassName(); this.writeLog = bc.writeLog(); this.adapter = adapter; this.keys = keys; this.method=method; //this.staticConstr=statConstr; this.constr=constr; this.page=bc.getPage(); this.suppressWSbeforeArg=bc.suppressWSbeforeArg; this.returnValue=bc.returnValue; this.output=bc.output; this.ps=bc.ps; } @Override public Factory getFactory() { return page.getFactory(); } /** * @return the id */ public String getId() { return id; } /** * @return the count */ public int getCount() { return count; } /** * @param count the count to set */ public int incCount() { return ++this.count; } public void resetCount() { this.count=0; } /** * @return the adapter */ public GeneratorAdapter getAdapter() { return adapter; } /** * @param adapter the adapter to set */ public void setAdapter(BytecodeContext bc) { this.adapter = bc.getAdapter(); } /** * @return the classWriter */ public ClassWriter getClassWriter() { return classWriter; } /** * @param classWriter the classWriter to set */ public void setClassWriter(ClassWriter classWriter) { this.classWriter = classWriter; } /** * @return the className */ public String getClassName() { return className; } /** * @param className the className to set */ public void setClassName(String className) { this.className = className; } public synchronized int registerKey(LitString lit) { int index = keys.indexOf(lit); if(index!=-1)return index;// calls the toString method of litString keys.add(lit); return keys.size()-1; } public List<LitString> getKeys() { return keys; } //private static BytecodeContext staticConstr; public void pushOnFinally(OnFinally onFinally) { tcf.push(onFinally); } public void popOnFinally() { tcf.pop(); } public Stack<OnFinally> getOnFinallyStack() { return tcf; } /** * @return the method */ public Method getMethod() { return method; } /** * @return the doSubFunctions */ public boolean doSubFunctions() { return doSubFunctions; } /** * @param doSubFunctions the doSubFunctions to set * @return */ public boolean changeDoSubFunctions(boolean doSubFunctions) { boolean old=this.doSubFunctions; this.doSubFunctions = doSubFunctions; return old; } /** * @return the currentTag */ public int getCurrentTag() { return currentTag; } /** * @param currentTag the currentTag to set */ public void setCurrentTag(int currentTag) { this.currentTag = currentTag; } public ConstrBytecodeContext getConstructor() { return constr; } public void visitLineNumber(int line) { this.line=line; getAdapter().visitLineNumber(line,getAdapter().mark()); } public int getLine() { return line; } public BytecodeContext getRoot() { return root; } public void setRoot(BytecodeContext root) { this.root= root; } public boolean writeLog() { return this.writeLog; } public Page getPage() { return page; } public boolean getSupressWSbeforeArg(){ return suppressWSbeforeArg; } public boolean getOutput() { return output; } public Config getConfig() { if(ps!=null) return ps.getMapping().getConfig(); return ThreadLocalPageContext.getConfig(); } /** * optional value maybe not exists! * @return PageSource if available otherwise null */ public PageSource getPageSource() { return ps; } public void finallyPush(OnFinally onf) { insideFinallies.push(onf); } public OnFinally finallyPop() { return insideFinallies.pop(); } public boolean insideFinally(OnFinally onf) { Iterator<OnFinally> it = insideFinallies.iterator(); while(it.hasNext()){ if(it.next()==onf) return true; } return false; } public void setReturn(int rtn) { this.rtn=rtn; } public int getReturn() { return rtn; } /** * should the Page return the last expression or not * @return */ public boolean returnValue() { return returnValue; } }