001    package railo.runtime.tag;
002    
003    import railo.commons.lang.StringUtil;
004    import railo.runtime.Mapping;
005    import railo.runtime.MappingImpl;
006    import railo.runtime.PageContextImpl;
007    import railo.runtime.PageSource;
008    import railo.runtime.config.Config;
009    import railo.runtime.config.ConfigWeb;
010    import railo.runtime.customtag.CustomTagUtil;
011    import railo.runtime.customtag.InitFile;
012    import railo.runtime.exp.ExpressionException;
013    import railo.runtime.exp.MissingIncludeException;
014    import railo.runtime.type.util.KeyConstants;
015    
016    /**
017    * Invokes a custom tag for use in CFML application pages.
018    **/
019    public final class Module extends CFTag {
020    
021            @Override
022            public void initFile() throws MissingIncludeException, ExpressionException {
023                    ConfigWeb config = pageContext.getConfig();
024            // MUSTMUST cache like ct
025                    //String[] filenames=getFileNames(config,getAppendix());// = appendix+'.'+config.getCFMLExtension();
026            
027                Object objTemplate =attributesScope.get(KeyConstants._template,null);
028                Object objName =attributesScope.get(KeyConstants._name,null);
029                source=null;
030                if(objTemplate!=null) {
031                            attributesScope.removeEL(KeyConstants._template);
032                        String template=objTemplate.toString();
033    
034                if(StringUtil.startsWith(template,'/'))  {
035                    PageSource[] sources = ((PageContextImpl)pageContext).getPageSources(template);
036                    PageSource ps = MappingImpl.isOK(sources);
037                    
038                    if(ps==null)
039                                            throw new MissingIncludeException(sources[0],"could not find template ["+template+"], file ["+sources[0].getDisplayPath()+"] doesn't exist");
040                    source=new InitFile(ps,template,template.endsWith('.'+pageContext.getConfig().getCFCExtension()));
041                }
042                else {
043                    source=new InitFile(pageContext.getCurrentPageSource().getRealPage(template),template,StringUtil.endsWithIgnoreCase(template,'.'+pageContext.getConfig().getCFCExtension()));
044                    if(!MappingImpl.isOK(source.getPageSource())){
045                                            throw new MissingIncludeException(source.getPageSource(),"could not find template ["+template+"], file ["+source.getPageSource().getDisplayPath()+"] doesn't exist");
046                    }
047                }
048                    
049                //attributesScope.removeEL(TEMPLATE);
050                setAppendix(source.getPageSource());
051                }
052                else if(objName!=null) {
053                            attributesScope.removeEL(KeyConstants._name);
054                    String[] filenames = toRealPath(config,objName.toString());
055                    boolean exist=false;
056                    
057                    // appcontext mappings
058                    Mapping[] ctms = pageContext.getApplicationContext().getCustomTagMappings(); 
059                    if(ctms!=null) {
060                            outer:for(int f=0;f<filenames.length;f++){
061                                    for(int i=0;i<ctms.length;i++){
062                                    source=new InitFile(ctms[i].getPageSource(filenames[f]),filenames[f],filenames[f].endsWith('.'+config.getCFCExtension()));
063                                    if(MappingImpl.isOK(source.getPageSource())) {
064                                            exist=true;
065                                            break outer;
066                                    }
067                                }
068                            }
069                    }
070                    
071                    // config mappings
072                    if(!exist) {
073                            ctms = config.getCustomTagMappings();
074                            outer:for(int f=0;f<filenames.length;f++){ 
075                                for(int i=0;i<ctms.length;i++){// TODO optimieren siehe CFTag
076                                    source=new InitFile(ctms[i].getPageSource(filenames[f]),filenames[f],filenames[f].endsWith('.'+config.getCFCExtension()));
077                                    if(MappingImpl.isOK(source.getPageSource())) {
078                                            exist=true;
079                                            break outer;
080                                    }
081                                }
082                            }
083                    }
084                
085                            if(!exist)
086                                    throw new ExpressionException("custom tag ("+CustomTagUtil.getDisplayName(config, objName.toString())+") is not defined in custom tag directory ["+(ctms.length==0?"no custom tag directory defined":CustomTagUtil.toString(ctms))+"]");
087                            
088                            setAppendix(source.getPageSource());
089                }
090                else {
091                    throw new ExpressionException("you must define attribute template or name for tag module");
092                }
093                
094            }
095    
096            private void setAppendix(PageSource source) {
097                    String appendix=source.getFileName();
098            int index=appendix.lastIndexOf('.');
099            appendix=appendix.substring(0,index);
100            setAppendix(appendix);
101            }
102    
103            /**
104             * translate a dot-notation path to a realpath
105         * @param dotPath
106         * @return realpath
107             * @throws ExpressionException 
108         */
109        private static String[] toRealPath(Config config ,String dotPath) throws ExpressionException {
110            dotPath=dotPath.trim();
111            
112            while(dotPath.indexOf('.')==0) {
113                dotPath=dotPath.substring(1);
114            }
115            int len=-1;
116            while((len=dotPath.length())>0 && dotPath.lastIndexOf('.')==len-1) {
117                dotPath=dotPath.substring(0,len-2);
118            }
119            //dotPath.replace('.','/')+".cfm";
120            return CustomTagUtil.getFileNames(config, dotPath.replace('.','/'));
121        }
122    }