package railo.runtime.compiler;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import railo.commons.io.IOUtil;
import railo.commons.io.res.Resource;
import railo.runtime.PageSource;
import railo.runtime.config.ConfigImpl;
import railo.runtime.exp.TemplateException;
import railo.transformer.bytecode.BytecodeException;
import railo.transformer.bytecode.Page;
import railo.transformer.bytecode.Position;
import railo.transformer.bytecode.util.ASMUtil;
import railo.transformer.bytecode.util.ClassRenamer;
import railo.transformer.cfml.tag.CFMLTransformer;
import railo.transformer.library.function.FunctionLib;
import railo.transformer.library.tag.TagLib;
import railo.transformer.util.AlreadyClassException;
/**
* CFML Compiler compiles CFML source templates
*/
public final class CFMLCompilerImpl implements CFMLCompiler {
private CFMLTransformer cfmlTransformer;
/**
* Constructor of the compiler
* @param config
*/
public CFMLCompilerImpl() {
cfmlTransformer=new CFMLTransformer();
}
@Override
public byte[] compile(ConfigImpl config,PageSource source, TagLib[] tld, FunctionLib[] fld,
Resource classRootDir, String className) throws TemplateException, IOException {
//synchronized(source){
//print.out("src:"+source.getDisplayPath());
//print.dumpStack();
Resource classFile=classRootDir.getRealResource(className+".class");
Resource classFileDirectory=classFile.getParentResource();
byte[] barr = null;
Page page = null;
if(!classFileDirectory.exists()) classFileDirectory.mkdirs();
try {
page = cfmlTransformer.transform(config,source,tld,fld);
barr = page.execute(source,classFile);
IOUtil.copy(new ByteArrayInputStream(barr), classFile,true);
return barr;
}
catch (AlreadyClassException ace) {
InputStream is=null;
try{
barr=IOUtil.toBytes(is=ace.getInputStream());
String srcName = ASMUtil.getClassName(barr);
// source is cfm and target cfc
if(srcName.endsWith("_cfm$cf") && className.endsWith("_cfc$cf"))
throw new TemplateException("source file ["+source.getDisplayPath()+"] contains the bytecode for a regular cfm template not for a component");
// source is cfc and target cfm
if(srcName.endsWith("_cfc$cf") && className.endsWith("_cfm$cf"))
throw new TemplateException("source file ["+source.getDisplayPath()+"] contains a component not a regular cfm template");
// rename class name when needed
if(!srcName.equals(className))barr=ClassRenamer.rename(barr, className);
barr=Page.setSourceLastModified(barr,source.getPhyscalFile().lastModified());
IOUtil.copy(new ByteArrayInputStream(barr), classFile,true);
}
finally {
IOUtil.closeEL(is);
}
return barr;
}
catch (BytecodeException bce) {
Position pos = bce.getPosition();
int line=pos==null?-1:pos.line;
int col=pos==null?-1:pos.column;
bce.addContext(source, line, col,null);
throw bce;
//throw new TemplateException(source,e.getLine(),e.getColumn(),e.getMessage());
}
/*finally {
}*/
//}
}
/* *
* @return Returns the cfmlTransformer.
* /
public CFMLTransformer getCfmlTransformer() {
return cfmlTransformer;
}*/
}