001    package railo.transformer.bytecode;
002    
003    import java.util.List;
004    import java.util.Stack;
005    
006    import org.objectweb.asm.ClassWriter;
007    import org.objectweb.asm.commons.GeneratorAdapter;
008    import org.objectweb.asm.commons.Method;
009    
010    import railo.commons.lang.StringUtil;
011    import railo.transformer.Context;
012    import railo.transformer.bytecode.extern.StringExternalizerWriter;
013    import railo.transformer.bytecode.literal.LitString;
014    import railo.transformer.bytecode.visitor.OnFinally;
015    
016    public class BytecodeContext implements Context {
017            
018    
019            private ClassWriter classWriter;
020            private GeneratorAdapter adapter;
021            private String className;
022            private List<LitString> keys;
023            private int count=0;
024            private Method method;
025            private boolean doSubFunctions=true;
026            private BytecodeContext staticConstr;
027            private BytecodeContext constr;
028            private final boolean supressWSbeforeArg;
029            
030            private static long _id=0;
031            private synchronized static String id() {
032                    if(_id<0)_id=0;
033                    return StringUtil.addZeros(++_id,4);
034            }
035            
036            private String id=id();
037            private Page page;
038    
039            public BytecodeContext(BytecodeContext statConstr,BytecodeContext constr,Page page,StringExternalizerWriter externalizer,List<LitString> keys,ClassWriter classWriter,String className, GeneratorAdapter adapter,
040                            Method method,boolean writeLog, boolean supressWSbeforeArg) {
041                    this.classWriter = classWriter;
042                    this.className = className;
043                    this.writeLog = writeLog;
044                    this.adapter = adapter;
045                    this.keys = keys;
046                    this.method=method;
047                    this.staticConstr=statConstr;
048                    this.constr=constr;
049                    this.externalizer=externalizer;
050                    this.page=page;
051                    this.supressWSbeforeArg=supressWSbeforeArg;
052            }
053            
054            public BytecodeContext(BytecodeContext statConstr,BytecodeContext constr,List<LitString> keys,BytecodeContext bc, GeneratorAdapter adapter,Method method) {
055                    this.classWriter = bc.getClassWriter();
056                    this.className = bc.getClassName();
057                    this.writeLog = bc.writeLog();
058                    this.externalizer=bc.externalizer;
059                    
060                    this.adapter = adapter;
061                    this.keys = keys;
062                    this.method=method;
063                    this.staticConstr=statConstr;
064                    this.constr=constr;
065                    this.page=bc.getPage();
066                    this.supressWSbeforeArg=bc.supressWSbeforeArg;
067            }
068            
069            /**
070             * @return the id
071             */
072            public String getId() {
073                    return id;
074            }
075            
076            /**
077             * @return the count
078             */
079            public int getCount() {
080                    return count;
081            }
082    
083            /**
084             * @param count the count to set
085             */
086            public int incCount() {
087                    return ++this.count;
088            }
089            public void resetCount() {
090                    this.count=0;
091            }
092            /**
093             * @return the adapter
094             */
095            public GeneratorAdapter getAdapter() {
096                    return adapter;
097            }
098            /**
099             * @param adapter the adapter to set
100             */
101            public void setAdapter(BytecodeContext bc) {
102                    this.adapter = bc.getAdapter();
103            }
104            /**
105             * @return the classWriter
106             */
107            public ClassWriter getClassWriter() {
108                    return classWriter;
109            }
110            /**
111             * @param classWriter the classWriter to set
112             */
113            public void setClassWriter(ClassWriter classWriter) {
114                    this.classWriter = classWriter;
115            }
116            /**
117             * @return the className
118             */
119            public String getClassName() {
120                    return className;
121            }
122            /**
123             * @param className the className to set
124             */
125            public void setClassName(String className) {
126                    this.className = className;
127            }
128    
129            public synchronized int registerKey(LitString lit)  {
130                    int index = keys.indexOf(lit);
131                    if(index!=-1)return index;// calls the toString method of litString
132                    
133                    keys.add(lit);
134                    
135                    return keys.size()-1;
136            }
137    
138            public List<LitString> getKeys() {
139                    return keys;
140            }
141    
142    
143            Stack<OnFinally> tcf=new Stack<OnFinally>();
144            private int currentTag;
145            private int line;
146            private BytecodeContext root;
147            private boolean writeLog;
148            private StringExternalizerWriter externalizer;
149            //private static BytecodeContext staticConstr;
150            
151            public void pushOnFinally(OnFinally onFinally) {
152                    tcf.push(onFinally);
153            }
154            public void popOnFinally() {
155                    tcf.pop();
156            }
157            
158            /*public void pushTryCatchFinallyData(TryCatchFinallyData data) {
159                    tcf.push(data);
160            }
161            public void popTryCatchFinallyData() {
162                    tcf.pop();
163            }*/
164            
165            public Stack<OnFinally> getOnFinallyStack() {
166                    return tcf;
167            }
168    
169            /**
170             * @return the method
171             */
172            public Method getMethod() {
173                    return method;
174            }
175    
176            /**
177             * @return the doSubFunctions
178             */
179            public boolean doSubFunctions() {
180                    return doSubFunctions;
181            }
182    
183            /**
184             * @param doSubFunctions the doSubFunctions to set
185             * @return 
186             */
187            public boolean changeDoSubFunctions(boolean doSubFunctions) {
188                    boolean old=this.doSubFunctions;
189                    this.doSubFunctions = doSubFunctions;
190                    return old;
191            }
192    
193            /**
194             * @return the currentTag
195             */
196            public int getCurrentTag() {
197                    return currentTag;
198            }
199    
200            /**
201             * @param currentTag the currentTag to set
202             */
203            public void setCurrentTag(int currentTag) {
204                    this.currentTag = currentTag;
205            }
206    
207            public BytecodeContext getStaticConstructor() {
208                    return staticConstr;
209            }
210            public BytecodeContext getConstructor() {
211                    return constr;
212            }
213    
214            public void visitLineNumber(int line) {
215                    this.line=line;
216                    getAdapter().visitLineNumber(line,getAdapter().mark());
217            }
218    
219            public int getLine() {
220                    return line;
221            }
222    
223            public BytecodeContext getRoot() {
224                    return root;
225            }
226            public void setRoot(BytecodeContext root) {
227                    this.root= root;
228            }
229    
230            public boolean writeLog() {
231                    return this.writeLog;
232            }
233    
234            public StringExternalizerWriter getStringExternalizerWriter() {
235                    return externalizer;
236            }
237    
238            public Page getPage() {
239                    return page;
240            }
241            
242            public boolean getSupressWSbeforeArg(){
243                    return supressWSbeforeArg;
244            }
245    }