001 package railo.runtime.compiler; 002 003 import java.io.ByteArrayInputStream; 004 import java.io.IOException; 005 import java.io.InputStream; 006 007 import railo.commons.io.IOUtil; 008 import railo.commons.io.res.Resource; 009 import railo.runtime.PageSource; 010 import railo.runtime.config.ConfigImpl; 011 import railo.runtime.exp.TemplateException; 012 import railo.transformer.bytecode.BytecodeException; 013 import railo.transformer.bytecode.Page; 014 import railo.transformer.bytecode.Position; 015 import railo.transformer.bytecode.util.ASMUtil; 016 import railo.transformer.bytecode.util.ClassRenamer; 017 import railo.transformer.cfml.tag.CFMLTransformer; 018 import railo.transformer.library.function.FunctionLib; 019 import railo.transformer.library.tag.TagLib; 020 import railo.transformer.util.AlreadyClassException; 021 022 023 024 /** 025 * CFML Compiler compiles CFML source templates 026 */ 027 public final class CFMLCompilerImpl implements CFMLCompiler { 028 029 private CFMLTransformer cfmlTransformer; 030 031 032 /** 033 * Constructor of the compiler 034 * @param config 035 */ 036 public CFMLCompilerImpl() { 037 cfmlTransformer=new CFMLTransformer(); 038 } 039 040 @Override 041 public byte[] compile(ConfigImpl config,PageSource source, TagLib[] tld, FunctionLib[] fld, 042 Resource classRootDir, String className) throws TemplateException, IOException { 043 //synchronized(source){ 044 //print.out("src:"+source.getDisplayPath()); 045 //print.dumpStack(); 046 Resource classFile=classRootDir.getRealResource(className+".class"); 047 Resource classFileDirectory=classFile.getParentResource(); 048 byte[] barr = null; 049 Page page = null; 050 051 if(!classFileDirectory.exists()) classFileDirectory.mkdirs(); 052 053 try { 054 page = cfmlTransformer.transform(config,source,tld,fld); 055 barr = page.execute(classFile); 056 IOUtil.copy(new ByteArrayInputStream(barr), classFile,true); 057 return barr; 058 } 059 catch (AlreadyClassException ace) { 060 InputStream is=null; 061 try{ 062 barr=IOUtil.toBytes(is=ace.getInputStream()); 063 064 String srcName = ASMUtil.getClassName(barr); 065 // source is cfm and target cfc 066 if(srcName.endsWith("_cfm$cf") && className.endsWith("_cfc$cf")) 067 throw new TemplateException("source file ["+source.getDisplayPath()+"] contains the bytecode for a regular cfm template not for a component"); 068 // source is cfc and target cfm 069 if(srcName.endsWith("_cfc$cf") && className.endsWith("_cfm$cf")) 070 throw new TemplateException("source file ["+source.getDisplayPath()+"] contains a component not a regular cfm template"); 071 072 // rename class name when needed 073 if(!srcName.equals(className))barr=ClassRenamer.rename(barr, className); 074 075 076 barr=Page.setSourceLastModified(barr,source.getPhyscalFile().lastModified()); 077 IOUtil.copy(new ByteArrayInputStream(barr), classFile,true); 078 079 } 080 finally { 081 IOUtil.closeEL(is); 082 } 083 return barr; 084 } 085 catch (BytecodeException bce) { 086 Position pos = bce.getPosition(); 087 int line=pos==null?-1:pos.line; 088 int col=pos==null?-1:pos.column; 089 bce.addContext(source, line, col,null); 090 throw bce; 091 //throw new TemplateException(source,e.getLine(),e.getColumn(),e.getMessage()); 092 } 093 /*finally { 094 095 }*/ 096 //} 097 } 098 099 /* * 100 * @return Returns the cfmlTransformer. 101 * / 102 public CFMLTransformer getCfmlTransformer() { 103 return cfmlTransformer; 104 }*/ 105 }