<<<<<<< HEAD
package railo.transformer.bytecode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
import railo.commons.io.res.Resource;
import railo.commons.lang.NumberUtil;
import railo.commons.lang.StringUtil;
import railo.runtime.component.ImportDefintion;
import railo.runtime.component.ImportDefintionImpl;
import railo.runtime.exp.TemplateException;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.StructImpl;
import railo.runtime.type.UDF;
import railo.runtime.type.scope.Undefined;
import railo.runtime.type.util.KeyConstants;
import railo.transformer.bytecode.expression.Expression;
import railo.transformer.bytecode.extern.StringExternalizerWriter;
import railo.transformer.bytecode.literal.LitString;
import railo.transformer.bytecode.statement.Argument;
import railo.transformer.bytecode.statement.HasBodies;
import railo.transformer.bytecode.statement.HasBody;
import railo.transformer.bytecode.statement.IFunction;
import railo.transformer.bytecode.statement.NativeSwitch;
import railo.transformer.bytecode.statement.tag.Attribute;
import railo.transformer.bytecode.statement.tag.Tag;
import railo.transformer.bytecode.statement.tag.TagImport;
import railo.transformer.bytecode.statement.tag.TagThread;
import railo.transformer.bytecode.statement.udf.Function;
import railo.transformer.bytecode.statement.udf.FunctionImpl;
import railo.transformer.bytecode.util.ASMConstants;
import railo.transformer.bytecode.util.ASMUtil;
import railo.transformer.bytecode.util.ExpressionUtil;
import railo.transformer.bytecode.util.Types;
import railo.transformer.bytecode.visitor.ArrayVisitor;
import railo.transformer.bytecode.visitor.ConditionVisitor;
}
}
new Type[]{Types.PAGE_CONTEXT}
);
Types.INT_VALUE,
});
new Type[]{}
// int getVersion()
);
// newInstance/initComponent/call
div.visitBegin();
if(isComponent()) {
Tag component=getComponent();
private final static Method VERSION = new Method(
"getVersion",
import railo.transformer.bytecode.visitor.DecisionIntVisitor;
import railo.transformer.bytecode.visitor.OnFinally;
import railo.transformer.bytecode.visitor.TryCatchFinallyVisitor;
/**
* represent a single Page like "index.cfm"
*/
public final class Page extends BodyBase {
public void doFinalize(BytecodeContext bc) {
ExpressionUtil.visitLine(bc, getEndLine()+1);
}
private static final Type KEY_IMPL = Type.getType(KeyImpl.class);
private static final Type KEY_CONSTANTS = Type.getType(KeyConstants.class);
private static final Method KEY_INIT = new Method(
"init",
Types.COLLECTION_KEY,
new Type[]{Types.STRING}
);
private static final Method KEY_INTERN = new Method(
"intern",
Types.COLLECTION_KEY,
new Type[]{Types.STRING}
);
// public static ImportDefintion getInstance(String fullname,ImportDefintion defaultValue)
private static final Method ID_GET_INSTANCE = new Method(
"getInstance",
Types.IMPORT_DEFINITIONS,
new Type[]{Types.STRING,Types.IMPORT_DEFINITIONS}
);
public final static Method STATIC_CONSTRUCTOR = Method.getMethod("void ()V");
//public final static Method CONSTRUCTOR = Method.getMethod("void ()V");
private static final Method CONSTRUCTOR = new Method(
"",
Types.VOID,
new Type[]{}//
);
private static final Method CONSTRUCTOR_PS = new Method(
"",
Types.VOID,
new Type[]{Types.PAGE_SOURCE}//
);
public static final Type STRUCT_IMPL = Type.getType(StructImpl.class);
private static final Method INIT_STRUCT_IMPL = new Method(
"",
Types.VOID,
new Type[]{}
);
// void call (railo.runtime.PageContext)
private final static Method CALL = new Method(
"call",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT}
);
/*/ void _try ()
private final static Method TRY = new Method(
"_try",
Types.VOID,
new Type[]{}
);*/
private final static Method SET_PAGE_SOURCE = new Method(
"setPageSource",
Types.VOID,
new Type[]{Types.PAGE_SOURCE}
);
// public ImportDefintion[] getImportDefintions()
private final static Method GET_IMPORT_DEFINITIONS = new Method(
"getImportDefintions",
Types.IMPORT_DEFINITIONS_ARRAY,
new Type[]{}
);
// long getSourceLastModified()
private final static Method LAST_MOD = new Method(
"getSourceLastModified",
Types.LONG_VALUE,
new Type[]{}
);
private final static Method COMPILE_TIME = new Method(
"getCompileTime",
Types.LONG_VALUE,
new Type[]{}
);
private static final Type USER_DEFINED_FUNCTION = Type.getType(UDF.class);
private static final Method UDF_CALL = new Method(
"udfCall",
Types.OBJECT,
new Type[]{Types.PAGE_CONTEXT, USER_DEFINED_FUNCTION, Types.INT_VALUE}
);
private static final Method THREAD_CALL = new Method(
"threadCall",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT, Types.INT_VALUE}
);
private static final Method UDF_DEFAULT_VALUE = new Method(
"udfDefaultValue",
Types.OBJECT,
new Type[]{Types.PAGE_CONTEXT, Types.INT_VALUE, Types.INT_VALUE}
);
private static final Method NEW_COMPONENT_IMPL_INSTANCE = new Method(
"newInstance",
Types.COMPONENT_IMPL,
new Type[]{Types.PAGE_CONTEXT,Types.STRING,Types.BOOLEAN_VALUE}
);
private static final Method NEW_INTERFACE_IMPL_INSTANCE = new Method(
"newInstance",
Types.INTERFACE_IMPL,
new Type[]{Types.STRING,Types.BOOLEAN_VALUE,Types.MAP}
);
// void init(PageContext pc,Component Impl c) throws PageException
private static final Method INIT_COMPONENT = new Method(
"initComponent",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_IMPL}
);
private static final Method INIT_INTERFACE = new Method(
"initInterface",
Types.VOID,
new Type[]{Types.INTERFACE_IMPL}
);
// public boolean setMode(int mode) {
private static final Method SET_MODE = new Method(
"setMode",
Types.INT_VALUE,
new Type[]{Types.INT_VALUE}
);
private static final Method CONSTR_INTERFACE_IMPL = new Method(
"",
Types.VOID,
new Type[]{
Types.INTERFACE_PAGE,
Types.STRING, // extends
Types.STRING, // hind
Types.STRING, // display
Types.STRING, // callpath
Types.BOOLEAN_VALUE, // realpath
Types.MAP, //interfaceudfs
Types.MAP // meta
}
);
//void init(PageContext pageContext,ComponentPage componentPage)
private static final Method INIT = new Method(
"init",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_PAGE}
);
private static final Method CHECK_INTERFACE = new Method(
"checkInterface",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_PAGE}
);
// boolean getOutput()
private static final Method GET_OUTPUT = new Method(
"getOutput",
Types.BOOLEAN_VALUE,
new Type[]{}
);
private static final Method PUSH_BODY = new Method(
"pushBody",
Types.BODY_CONTENT,
new Type[]{}
);
/*/ boolean setSilent()
private static final Method SET_SILENT = new Method(
"setSilent",
Types.BOOLEAN_VALUE,
new Type[]{}
);
*/
// Scope beforeCall(PageContext pc)
private static final Method BEFORE_CALL = new Method(
"beforeCall",
Types.VARIABLES,
private static final Method TO_PAGE_EXCEPTION = new Method(
"toPageException",
Types.PAGE_EXCEPTION,
new Type[]{Types.THROWABLE});
// boolean unsetSilent()
/*private static final Method UNSET_SILENT = new Method(
"unsetSilent",
Types.BOOLEAN_VALUE,
new Type[]{}
);*/
// void afterCall(PageContext pc, Scope parent)
private static final Method AFTER_CALL = new Method(
"afterConstructor",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.VARIABLES}
);
// ComponentImpl(ComponentPage,boolean, String, String, String) NS==No Style
// Component Impl(ComponentPage,boolean, String, String, String, String) WS==With Style
private static final Method CONSTR_COMPONENT_IMPL = new Method(
"",
Types.VOID,
new Type[]{
Types.COMPONENT_PAGE,
Types.BOOLEAN,
Types.BOOLEAN_VALUE,
Types.STRING,
Types.STRING,
Types.STRING,
Types.STRING,
Types.STRING,
Types.BOOLEAN_VALUE,
Types.STRING,
Types.BOOLEAN_VALUE,
Types.BOOLEAN_VALUE,
STRUCT_IMPL
}
);
private static final Method SET_EL = new Method(
"setEL",
Types.OBJECT,
new Type[]{Types.STRING,Types.OBJECT}
);
private static final Method UNDEFINED_SCOPE = new Method(
"us",
Types.UNDEFINED,
new Type[]{}
);
private static final Method FLUSH_AND_POP = new Method(
"flushAndPop",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.BODY_CONTENT}
);
private static final Method CLEAR_AND_POP = new Method(
"clearAndPop",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.BODY_CONTENT}
);
public static final byte CF = (byte)207;
public static final byte _33 = (byte)51;
private static final boolean ADD_C33 = false;
//private static final String SUB_CALL_UDF = "udfCall";
private static final String SUB_CALL_UDF = "_";
private int version;
private long lastModifed;
private String name;
//private Body body=new Body();
private Resource source;
private final String path;
private boolean isComponent;
private boolean isInterface;
private List functions=new ArrayList();
private List threads=new ArrayList();
private boolean _writeLog;
private StringExternalizerWriter externalizer;
public Page(Resource source,String name,int version, long lastModifed, boolean writeLog) {
name=name.replace('.', '/');
//body.setParent(this);
this.name=name;
this.version=version;
this.lastModifed=lastModifed;
this.source=source;
this.path=source.getAbsolutePath();
this._writeLog=writeLog;
}
/**
* result byte code as binary array
* @param classFile
* @return byte code
* @throws IOException
* @throws TemplateException
*/
public byte[] execute(Resource classFile) throws BytecodeException {
Resource p = classFile.getParentResource().getRealResource(classFile.getName()+".txt");
this.externalizer=new StringExternalizerWriter(p);
List keys=new ArrayList();
ClassWriter cw = ASMUtil.getClassWriter();
//ClassWriter cw = new ClassWriter(true);
ArrayList list = new ArrayList();
getImports(list, this);
// parent
String parent="railo/runtime/Page";
if(isComponent()) parent="railo/runtime/ComponentPage";
else if(isInterface()) parent="railo/runtime/InterfacePage";
cw.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL, name, null, parent, null);
cw.visitSource(this.path, null);
// static constructor
GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,STATIC_CONSTRUCTOR,null,null,cw);
BytecodeContext statConstr = new BytecodeContext(null,null,this,externalizer,keys,cw,name,ga,STATIC_CONSTRUCTOR,writeLog());
// private static ImportDefintion[] test=new ImportDefintion[]{...};
if(list.size()>0){
FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC,
"imports", "[Lrailo/runtime/component/ImportDefintion;", null, null);
fv.visitEnd();
GeneratorAdapter adapter = statConstr.getAdapter();
ArrayVisitor av=new ArrayVisitor();
av.visitBegin(adapter,Types.IMPORT_DEFINITIONS,list.size());
int index=0;
Iterator it = list.iterator();
while(it.hasNext()){
av.visitBeginItem(adapter,index++);
adapter.push(it.next());
ASMConstants.NULL(adapter);
adapter.invokeStatic(Types.IMPORT_DEFINITIONS_IMPL, ID_GET_INSTANCE);
av.visitEndItem(adapter);
}
av.visitEnd();
adapter.visitFieldInsn(Opcodes.PUTSTATIC, name, "imports", "[Lrailo/runtime/component/ImportDefintion;");
}
// constructor
ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,CONSTRUCTOR_PS,null,null,cw);
BytecodeContext constr = new BytecodeContext(null,null,this,externalizer,keys,cw,name,ga,CONSTRUCTOR_PS,writeLog());
ga.loadThis();
Type t=Types.PAGE;
if(isComponent())t=Types.COMPONENT_PAGE;
else if(isInterface())t=Types.INTERFACE_PAGE;
ga.invokeConstructor(t, CONSTRUCTOR);
//setPageSource(pageSource);
ga.visitVarInsn(Opcodes.ALOAD, 0);
ga.visitVarInsn(Opcodes.ALOAD, 1);
ga.invokeVirtual(t, SET_PAGE_SOURCE);
// getVersion
GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , VERSION, null, null, cw);
adapter.push(version);
adapter.returnValue();
adapter.endMethod();
// public ImportDefintion[] getImportDefintions()
if(list.size()>0){
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , GET_IMPORT_DEFINITIONS, null, null, cw);
adapter.visitFieldInsn(Opcodes.GETSTATIC, name, "imports", "[Lrailo/runtime/component/ImportDefintion;");
adapter.returnValue();
adapter.endMethod();
}
// getSourceLastModified
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , LAST_MOD, null, null, cw);
adapter.push(lastModifed);
adapter.returnValue();
adapter.endMethod();
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , COMPILE_TIME, null, null, cw);
adapter.push(System.currentTimeMillis());
adapter.returnValue();
adapter.endMethod();
adapter.visitInsn(Opcodes.ACONST_NULL);
writeOutNewComponent(statConstr,constr,keys,cw,component);
writeOutInitComponent(statConstr,constr,keys,cw,component);
}
else if(isInterface()) {
Tag interf=getInterface();
writeOutNewInterface(statConstr,constr,keys,cw,interf);
writeOutInitInterface(statConstr,constr,keys,cw,interf);
}
else {
writeOutCall(statConstr,constr,keys,cw);
}
// udfCall
Function[] functions=getFunctions();
ConditionVisitor cv;
DecisionIntVisitor div;
// less/equal than 10 functions
if(functions.length==0 || isInterface()){}
else if(functions.length<=10) {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_CALL, null, new Type[]{Types.THROWABLE}, cw);
BytecodeContext bc = new BytecodeContext(statConstr,constr,this,externalizer,keys,cw,name,adapter,UDF_CALL,writeLog());
if(functions.length==0){}
else if(functions.length==1){
ExpressionUtil.visitLine(bc,functions[0].getStartLine());
functions[0].getBody().writeOut(bc);
ExpressionUtil.visitLine(bc,functions[0].getEndLine());
}
else writeOutUdfCallInner(bc,functions,0,functions.length);
adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
adapter.endMethod();
}
// more than 10 functions
else {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_CALL, null, new Type[]{Types.THROWABLE}, cw);
BytecodeContext bc = new BytecodeContext(statConstr,constr,this,externalizer,keys,cw,name,adapter,UDF_CALL,writeLog());
cv = new ConditionVisitor();
cv.visitBefore();
int count=0;
for(int i=0;ifunctions.length?functions.length:i+10);
adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
adapter.endMethod();
}
}
// threadCall
TagThread[] threads=getThreads();
if(threads.length>0) {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , THREAD_CALL, null, new Type[]{Types.THROWABLE}, cw);
writeOutThreadCallInner(new BytecodeContext(statConstr,constr,this,externalizer,keys,cw,name,adapter,THREAD_CALL,writeLog()),threads,0,threads.length);
//adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
barr[i+2]=bLastMod[i];
adapter.endMethod();
}
// udfDefaultValue
// less/equal than 10 functions
if(functions.length==0 || isInterface()) {}
else if(functions.length<=10) {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_DEFAULT_VALUE, null, new Type[]{Types.PAGE_EXCEPTION}, cw);
writeUdfDefaultValueInner(new BytecodeContext(statConstr,constr,this,externalizer,keys,cw,name,adapter,UDF_DEFAULT_VALUE,writeLog()),functions,0,functions.length);
ASMConstants.NULL(adapter);
adapter.returnValue();
adapter.endMethod();
}
else {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_DEFAULT_VALUE, null, new Type[]{Types.PAGE_EXCEPTION}, cw);
BytecodeContext bc = new BytecodeContext(statConstr,constr,this,externalizer,keys,cw,name,adapter,UDF_DEFAULT_VALUE,writeLog());
cv = new ConditionVisitor();
cv.visitBefore();
int count=0;
for(int i=0;ifunctions.length?functions.length:i+10);
adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
adapter.endMethod();
}
registerFields(statConstr,keys);
statConstr.getAdapter().returnValue();
statConstr.getAdapter().endMethod();
adapter = constr.getAdapter();//new GeneratorAdapter(Opcodes.ACC_PUBLIC,CONSTRUCTOR,null,null,cw);
adapter.returnValue();
adapter.endMethod();
try {
if(externalizer!=null)externalizer.writeOut();
} catch (IOException e) {
throw new BytecodeException(e.getMessage(), -1);
}
if(ADD_C33) {
byte[] tmp = cw.toByteArray();
byte[] bLastMod=NumberUtil.longToByteArray(lastModifed);
byte[] barr = new byte[tmp.length+10];
// Magic Number
barr[0]=CF; // CF
barr[1]=_33; // 33
// Last Modified
for(int i=0;i<8;i++){
for(int i=0;i functions=new ArrayList();
getFunctions(functions,bc,body,pageType);
String className = Types.UDF_PROPERTIES_ARRAY.toString();
//FieldVisitor fv = bc.getClassWriter().visitField(Opcodes.ACC_PRIVATE , "udfs",className , null, null);
//fv.visitEnd();
BytecodeContext constr = bc.getConstructor();
GeneratorAdapter cga = constr.getAdapter();
cga.visitVarInsn(Opcodes.ALOAD, 0);
cga.push(functions.size());
//cga.visitTypeInsn(Opcodes.ANEWARRAY, Types.UDF_PROPERTIES.toString());
cga.newArray(Types.UDF_PROPERTIES);
cga.visitFieldInsn(Opcodes.PUTFIELD, bc.getClassName(), "udfs", className);
Iterator it = functions.iterator();
while(it.hasNext()){
it.next().writeOut(bc, pageType);
}
if(pageType==IFunction.PAGE_TYPE_COMPONENT) {
GeneratorAdapter adapter = bc.getAdapter();
adapter.loadArg(1);
adapter.loadArg(0);
adapter.visitVarInsn(Opcodes.ALOAD, 0);
adapter.invokeVirtual(Types.COMPONENT_IMPL, CHECK_INTERFACE);
}
if(pageType!=IFunction.PAGE_TYPE_INTERFACE){
BodyBase.writeOut(bc.getStaticConstructor(),bc.getConstructor(),bc.getKeys(),body.getStatements(), bc);
}
}
private static void getImports(List list,Body body) throws BytecodeException {
if(ASMUtil.isEmpty(body)) return;
Statement stat;
List stats = body.getStatements();
int len=stats.size();
for(int i=0;i functions,BytecodeContext bc, Body body, int pageType) throws BytecodeException {
//writeOutImports(bc, body, pageType);
if(ASMUtil.isEmpty(body)) return;
Statement stat;
List stats = body.getStatements();
int len=stats.size();
for(int i=0;i it = functions.iterator();
while(it.hasNext()){
if(it.next() instanceof FunctionImpl)indexes[IFunction.ARRAY_INDEX]++;
}
indexes[IFunction.VALUE_INDEX]=functions.size();
functions.add(function);
return indexes;
}
public int addThread(TagThread thread) {
threads.add(thread);
return threads.size()-1;
}
public static byte[] setSourceLastModified(byte[] barr, long lastModified) {
ClassReader cr = new ClassReader(barr);
ClassWriter cw = ASMUtil.getClassWriter();
ClassAdapter ca = new SourceLastModifiedClassAdapter(cw,lastModified);
cr.accept(ca, ClassReader.SKIP_DEBUG);
return cw.toByteArray();
}
}
class SourceLastModifiedClassAdapter extends ClassAdapter {
private long lastModified;
public SourceLastModifiedClassAdapter(ClassWriter cw, long lastModified) {
super(cw);
this.lastModified=lastModified;
}
public MethodVisitor visitMethod(int access,String name, String desc, String signature, String[] exceptions) {
if(!name.equals("getSourceLastModified"))return super.visitMethod(access,name, desc, signature, exceptions);
MethodVisitor mv = cv.visitMethod(access,name, desc, signature, exceptions);
mv.visitCode();
mv.visitLdcInsn(Long.valueOf(lastModified));
mv.visitInsn(Opcodes.LRETURN);
mv.visitEnd();
return mv;
}
}
=======
package railo.transformer.bytecode;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.objectweb.asm.ClassAdapter;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
//void init(PageContext pageContext,ComponentPage componentPage)
import org.objectweb.asm.commons.Method;
import railo.commons.io.res.Resource;
import railo.commons.lang.NumberUtil;
import railo.commons.lang.StringUtil;
import railo.runtime.component.ImportDefintion;
import railo.runtime.exp.TemplateException;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.StructImpl;
import railo.runtime.type.UDF;
import railo.runtime.type.scope.Undefined;
import railo.runtime.type.util.KeyConstants;
import railo.transformer.bytecode.expression.Expression;
import railo.transformer.bytecode.extern.StringExternalizerWriter;
import railo.transformer.bytecode.literal.LitString;
import railo.transformer.bytecode.statement.Argument;
import railo.transformer.bytecode.statement.Function;
import railo.transformer.bytecode.statement.HasBodies;
import railo.transformer.bytecode.statement.HasBody;
import railo.transformer.bytecode.statement.IFunction;
import railo.transformer.bytecode.statement.NativeSwitch;
import railo.transformer.bytecode.statement.tag.Attribute;
import railo.transformer.bytecode.statement.tag.Tag;
import railo.transformer.bytecode.statement.tag.TagImport;
import railo.transformer.bytecode.statement.tag.TagThread;
import railo.transformer.bytecode.util.ASMConstants;
import railo.transformer.bytecode.util.ASMUtil;
import railo.transformer.bytecode.util.ExpressionUtil;
import railo.transformer.bytecode.util.Types;
import railo.transformer.bytecode.visitor.ArrayVisitor;
import railo.transformer.bytecode.visitor.ConditionVisitor;
import railo.transformer.bytecode.visitor.DecisionIntVisitor;
import railo.transformer.bytecode.visitor.TryCatchFinallyVisitor;
/**
* represent a single Page like "index.cfm"
*/
public final class Page extends BodyBase {
public void doFinalize(BytecodeContext bc) {
ExpressionUtil.visitLine(bc, getEndLine()+1);
}
private static final Type KEY_IMPL = Type.getType(KeyImpl.class);
private static final Type KEY_CONSTANTS = Type.getType(KeyConstants.class);
private static final Method KEY_INIT = new Method(
"init",
Types.COLLECTION_KEY,
new Type[]{Types.STRING}
);
private static final Method KEY_INTERN = new Method(
"intern",
Types.COLLECTION_KEY,
new Type[]{Types.STRING}
);
// public static ImportDefintion getInstance(String fullname,ImportDefintion defaultValue)
private static final Method ID_GET_INSTANCE = new Method(
"getInstance",
Types.IMPORT_DEFINITIONS,
new Type[]{Types.STRING,Types.IMPORT_DEFINITIONS}
);
public final static Method STATIC_CONSTRUCTOR = Method.getMethod("void ()V");
//public final static Method CONSTRUCTOR = Method.getMethod("void ()V");
private static final Method CONSTRUCTOR = new Method(
"",
Types.VOID,
new Type[]{}//
);
private static final Method CONSTRUCTOR_PS = new Method(
"",
Types.VOID,
new Type[]{Types.PAGE_SOURCE}//
);
public static final Type STRUCT_IMPL = Type.getType(StructImpl.class);
private static final Method INIT_STRUCT_IMPL = new Method(
"",
Types.VOID,
new Type[]{}
);
// void call (railo.runtime.PageContext)
private final static Method CALL = new Method(
"call",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT}
);
/*/ void _try ()
private final static Method TRY = new Method(
"_try",
Types.VOID,
new Type[]{}
);*/
// int getVersion()
private final static Method VERSION = new Method(
"getVersion",
Types.INT_VALUE,
new Type[]{}
);
private final static Method SET_PAGE_SOURCE = new Method(
"setPageSource",
Types.VOID,
new Type[]{Types.PAGE_SOURCE}
);
// public ImportDefintion[] getImportDefintions()
private final static Method GET_IMPORT_DEFINITIONS = new Method(
"getImportDefintions",
Types.IMPORT_DEFINITIONS_ARRAY,
new Type[]{}
);
// long getSourceLastModified()
private final static Method LAST_MOD = new Method(
"getSourceLastModified",
Types.LONG_VALUE,
new Type[]{}
);
private final static Method COMPILE_TIME = new Method(
"getCompileTime",
Types.LONG_VALUE,
new Type[]{}
);
private static final Type USER_DEFINED_FUNCTION = Type.getType(UDF.class);
private static final Method UDF_CALL = new Method(
"udfCall",
Types.OBJECT,
new Type[]{Types.PAGE_CONTEXT, USER_DEFINED_FUNCTION, Types.INT_VALUE}
);
private static final Method THREAD_CALL = new Method(
"threadCall",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT, Types.INT_VALUE}
);
private static final Method UDF_DEFAULT_VALUE = new Method(
"udfDefaultValue",
Types.OBJECT,
new Type[]{Types.PAGE_CONTEXT, Types.INT_VALUE, Types.INT_VALUE}
);
private static final Method NEW_COMPONENT_IMPL_INSTANCE = new Method(
"newInstance",
Types.COMPONENT_IMPL,
new Type[]{Types.PAGE_CONTEXT,Types.STRING,Types.BOOLEAN_VALUE}
);
private static final Method NEW_INTERFACE_IMPL_INSTANCE = new Method(
"newInstance",
Types.INTERFACE_IMPL,
new Type[]{Types.STRING,Types.BOOLEAN_VALUE,Types.MAP}
);
// void init(PageContext pc,Component Impl c) throws PageException
private static final Method INIT_COMPONENT = new Method(
"initComponent",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_IMPL}
);
private static final Method INIT_INTERFACE = new Method(
"initInterface",
Types.VOID,
new Type[]{Types.INTERFACE_IMPL}
);
// public boolean setMode(int mode) {
private static final Method SET_MODE = new Method(
"setMode",
Types.INT_VALUE,
new Type[]{Types.INT_VALUE}
);
private static final Method CONSTR_INTERFACE_IMPL = new Method(
"",
Types.VOID,
new Type[]{
Types.INTERFACE_PAGE,
Types.STRING, // extends
Types.STRING, // hind
Types.STRING, // display
Types.STRING, // callpath
Types.BOOLEAN_VALUE, // realpath
Types.MAP, //interfaceudfs
Types.MAP // meta
}
);
private static final Method INIT = new Method(
ga.visitVarInsn(Opcodes.ALOAD, 1);
LitString value;
}
"init",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_PAGE}
);
private static final Method CHECK_INTERFACE = new Method(
"checkInterface",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.COMPONENT_PAGE}
);
// boolean getOutput()
private static final Method GET_OUTPUT = new Method(
"getOutput",
Types.BOOLEAN_VALUE,
new Type[]{}
);
private static final Method PUSH_BODY = new Method(
"pushBody",
Types.BODY_CONTENT,
new Type[]{}
);
/*/ boolean setSilent()
private static final Method SET_SILENT = new Method(
"setSilent",
Types.BOOLEAN_VALUE,
new Type[]{}
);
*/
// Scope beforeCall(PageContext pc)
private static final Method BEFORE_CALL = new Method(
"beforeCall",
Types.VARIABLES,
new Type[]{Types.PAGE_CONTEXT}
);
private static final Method TO_PAGE_EXCEPTION = new Method(
"toPageException",
Types.PAGE_EXCEPTION,
new Type[]{Types.THROWABLE});
// boolean unsetSilent()
/*private static final Method UNSET_SILENT = new Method(
"unsetSilent",
Types.BOOLEAN_VALUE,
new Type[]{}
);*/
// void afterCall(PageContext pc, Scope parent)
private static final Method AFTER_CALL = new Method(
"afterConstructor",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.VARIABLES}
);
// ComponentImpl(ComponentPage,boolean, String, String, String) NS==No Style
// Component Impl(ComponentPage,boolean, String, String, String, String) WS==With Style
private static final Method CONSTR_COMPONENT_IMPL = new Method(
"",
Types.VOID,
new Type[]{
Types.COMPONENT_PAGE,
Types.BOOLEAN,
Types.BOOLEAN_VALUE,
Types.STRING,
Types.STRING,
Types.STRING,
Types.STRING,
Types.STRING,
Types.BOOLEAN_VALUE,
Types.STRING,
Types.BOOLEAN_VALUE,
Types.BOOLEAN_VALUE,
STRUCT_IMPL
}
);
private static final Method SET_EL = new Method(
"setEL",
Types.OBJECT,
new Type[]{Types.STRING,Types.OBJECT}
);
private static final Method UNDEFINED_SCOPE = new Method(
"us",
Types.UNDEFINED,
new Type[]{}
);
private static final Method FLUSH_AND_POP = new Method(
"flushAndPop",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.BODY_CONTENT}
);
private static final Method CLEAR_AND_POP = new Method(
"clearAndPop",
Types.VOID,
new Type[]{Types.PAGE_CONTEXT,Types.BODY_CONTENT}
);
public static final byte CF = (byte)207;
public static final byte _33 = (byte)51;
private static final boolean ADD_C33 = false;
//private static final String SUB_CALL_UDF = "udfCall";
private static final String SUB_CALL_UDF = "_";
private int version;
private long lastModifed;
private String name;
//private Body body=new Body();
private Resource source;
private final String path;
private boolean isComponent;
private boolean isInterface;
private List functions=new ArrayList();
private List threads=new ArrayList();
private boolean _writeLog;
private StringExternalizerWriter externalizer;
public Page(Resource source,String name,int version, long lastModifed, boolean writeLog) {
name=name.replace('.', '/');
//body.setParent(this);
this.name=name;
this.version=version;
this.lastModifed=lastModifed;
this.source=source;
this.path=source.getAbsolutePath();
this._writeLog=writeLog;
}
/**
* result byte code as binary array
* @param classFile
* @return byte code
* @throws IOException
* @throws TemplateException
*/
public byte[] execute(Resource classFile) throws BytecodeException {
try {
Resource p = classFile.getParentResource().getRealResource(classFile.getName()+".txt");
this.externalizer=new StringExternalizerWriter(p);
} catch (IOException e) {}
List keys=new ArrayList();
ClassWriter cw = ASMUtil.getClassWriter();
//ClassWriter cw = new ClassWriter(true);
ArrayList list = new ArrayList();
getImports(list, this);
// parent
String parent="railo/runtime/PagePlus";// FUTURE use Page instead of PagePlus
if(isComponent()) parent="railo/runtime/ComponentPage";
else if(isInterface()) parent="railo/runtime/InterfacePage";
cw.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL, name, null, parent, null);
cw.visitSource(this.path, null);
// static constructor
GeneratorAdapter ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,STATIC_CONSTRUCTOR,null,null,cw);
BytecodeContext statConstr = new BytecodeContext(null,null,externalizer,keys,cw,name,ga,STATIC_CONSTRUCTOR,writeLog());
// private static ImportDefintion[] test=new ImportDefintion[]{...};
if(list.size()>0){
FieldVisitor fv = cw.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL + Opcodes.ACC_STATIC,
"imports", "[Lrailo/runtime/component/ImportDefintion;", null, null);
fv.visitEnd();
GeneratorAdapter adapter = statConstr.getAdapter();
ArrayVisitor av=new ArrayVisitor();
av.visitBegin(adapter,Types.IMPORT_DEFINITIONS,list.size());
int index=0;
Iterator it = list.iterator();
while(it.hasNext()){
av.visitBeginItem(adapter,index++);
adapter.push(it.next());
ASMConstants.NULL(adapter);
adapter.invokeStatic(Types.IMPORT_DEFINITIONS, ID_GET_INSTANCE);
av.visitEndItem(adapter);
}
av.visitEnd();
adapter.visitFieldInsn(Opcodes.PUTSTATIC, name, "imports", "[Lrailo/runtime/component/ImportDefintion;");
}
// constructor
ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC,CONSTRUCTOR_PS,null,null,cw);
BytecodeContext constr = new BytecodeContext(null,null,externalizer,keys,cw,name,ga,CONSTRUCTOR_PS,writeLog());
ga.loadThis();
Type t=Types.PAGE_PLUS;
if(isComponent())t=Types.COMPONENT_PAGE;
else if(isInterface())t=Types.INTERFACE_PAGE;
ga.invokeConstructor(t, CONSTRUCTOR);
//setPageSource(pageSource);
ga.visitVarInsn(Opcodes.ALOAD, 0);
ga.invokeVirtual(t, SET_PAGE_SOURCE);
// mv.visitMethodInsn(INVOKEVIRTUAL, "railo/runtime/PagePlus", "setPageSource", "(Lrailo/runtime/PageSource;)V");
// getVersion
GeneratorAdapter adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , VERSION, null, null, cw);
adapter.push(version);
adapter.returnValue();
adapter.endMethod();
// public ImportDefintion[] getImportDefintions()
if(list.size()>0){
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , GET_IMPORT_DEFINITIONS, null, null, cw);
adapter.visitFieldInsn(Opcodes.GETSTATIC, name, "imports", "[Lrailo/runtime/component/ImportDefintion;");
adapter.returnValue();
adapter.endMethod();
}
// getSourceLastModified
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , LAST_MOD, null, null, cw);
adapter.push(lastModifed);
adapter.returnValue();
adapter.endMethod();
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , COMPILE_TIME, null, null, cw);
adapter.push(System.currentTimeMillis());
adapter.returnValue();
adapter.endMethod();
// newInstance/initComponent/call
if(isComponent()) {
Tag component=getComponent();
writeOutNewComponent(statConstr,constr,keys,cw,component);
writeOutInitComponent(statConstr,constr,keys,cw,component);
}
else if(isInterface()) {
Tag interf=getInterface();
writeOutNewInterface(statConstr,constr,keys,cw,interf);
writeOutInitInterface(statConstr,constr,keys,cw,interf);
}
else {
writeOutCall(statConstr,constr,keys,cw);
}
// udfCall
Function[] functions=getFunctions();
ConditionVisitor cv;
DecisionIntVisitor div;
// less/equal than 10 functions
if(functions.length==0 || isInterface()){}
else if(functions.length<=10) {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_CALL, null, new Type[]{Types.THROWABLE}, cw);
BytecodeContext bc = new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_CALL,writeLog());
if(functions.length==0){}
else if(functions.length==1){
ExpressionUtil.visitLine(bc,functions[0].getStartLine());
functions[0].getBody().writeOut(bc);
}
ExpressionUtil.visitLine(bc,functions[0].getEndLine());
}
else writeOutUdfCallInner(bc,functions,0,functions.length);
adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
adapter.endMethod();
}
// more than 10 functions
else {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_CALL, null, new Type[]{Types.THROWABLE}, cw);
BytecodeContext bc = new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_CALL,writeLog());
cv = new ConditionVisitor();
cv.visitBefore();
int count=0;
for(int i=0;ifunctions.length?functions.length:i+10);
adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
adapter.endMethod();
}
}
// threadCall
TagThread[] threads=getThreads();
if(threads.length>0) {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , THREAD_CALL, null, new Type[]{Types.THROWABLE}, cw);
writeOutThreadCallInner(new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,THREAD_CALL,writeLog()),threads,0,threads.length);
//adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
adapter.endMethod();
}
// udfDefaultValue
// less/equal than 10 functions
if(functions.length==0 || isInterface()) {}
else if(functions.length<=10) {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_DEFAULT_VALUE, null, new Type[]{Types.PAGE_EXCEPTION}, cw);
writeUdfDefaultValueInner(new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_DEFAULT_VALUE,writeLog()),functions,0,functions.length);
ASMConstants.NULL(adapter);
adapter.returnValue();
adapter.endMethod();
}
else {
adapter = new GeneratorAdapter(Opcodes.ACC_PUBLIC+Opcodes.ACC_FINAL , UDF_DEFAULT_VALUE, null, new Type[]{Types.PAGE_EXCEPTION}, cw);
BytecodeContext bc = new BytecodeContext(statConstr,constr,externalizer,keys,cw,name,adapter,UDF_DEFAULT_VALUE,writeLog());
cv = new ConditionVisitor();
cv.visitBefore();
int count=0;
for(int i=0;ifunctions.length?functions.length:i+10);
adapter.visitInsn(Opcodes.ACONST_NULL);
adapter.returnValue();
adapter.endMethod();
}
}
registerFields(statConstr,keys);
statConstr.getAdapter().returnValue();
statConstr.getAdapter().endMethod();
adapter = constr.getAdapter();//new GeneratorAdapter(Opcodes.ACC_PUBLIC,CONSTRUCTOR,null,null,cw);
adapter.returnValue();
adapter.endMethod();
try {
if(externalizer!=null)externalizer.writeOut();
} catch (IOException e) {
throw new BytecodeException(e.getMessage(), -1);
}
if(ADD_C33) {
byte[] tmp = cw.toByteArray();
byte[] bLastMod=NumberUtil.longToByteArray(lastModifed);
byte[] barr = new byte[tmp.length+10];
// Magic Number
barr[0]=CF; // CF
barr[1]=_33; // 33
// Last Modified
for(int i=0;i<8;i++){
barr[i+2]=bLastMod[i];
}
for(int i=0;i functions=new ArrayList();
getFunctions(functions,bc,body,pageType);
String className = Types.UDF_PROPERTIES_ARRAY.toString();
//FieldVisitor fv = bc.getClassWriter().visitField(Opcodes.ACC_PRIVATE , "udfs",className , null, null);
//fv.visitEnd();
BytecodeContext constr = bc.getConstructor();
GeneratorAdapter cga = constr.getAdapter();
cga.visitVarInsn(Opcodes.ALOAD, 0);
cga.push(functions.size());
//cga.visitTypeInsn(Opcodes.ANEWARRAY, Types.UDF_PROPERTIES.toString());
cga.newArray(Types.UDF_PROPERTIES);
cga.visitFieldInsn(Opcodes.PUTFIELD, bc.getClassName(), "udfs", className);
Iterator it = functions.iterator();
while(it.hasNext()){
it.next().writeOut(bc, pageType);
}
if(pageType==IFunction.PAGE_TYPE_COMPONENT) {
GeneratorAdapter adapter = bc.getAdapter();
adapter.loadArg(1);
adapter.loadArg(0);
adapter.visitVarInsn(Opcodes.ALOAD, 0);
adapter.invokeVirtual(Types.COMPONENT_IMPL, CHECK_INTERFACE);
}
if(pageType!=IFunction.PAGE_TYPE_INTERFACE){
BodyBase.writeOut(bc.getStaticConstructor(),bc.getConstructor(),bc.getKeys(),body.getStatements(), bc);
}
}
private static void getImports(List list,Body body) throws BytecodeException {
if(ASMUtil.isEmpty(body)) return;
Statement stat;
List stats = body.getStatements();
int len=stats.size();
for(int i=0;i functions,BytecodeContext bc, Body body, int pageType) throws BytecodeException {
//writeOutImports(bc, body, pageType);
if(ASMUtil.isEmpty(body)) return;
Statement stat;
List stats = body.getStatements();
int len=stats.size();
for(int i=0;i>>>>>> 6874c434a7a0fdf4e9b3ef495c5db191b50f57af |