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    }