001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.tag;
020
021import lucee.commons.lang.StringUtil;
022import lucee.runtime.Mapping;
023import lucee.runtime.MappingImpl;
024import lucee.runtime.PageContextImpl;
025import lucee.runtime.PageSource;
026import lucee.runtime.config.Config;
027import lucee.runtime.config.ConfigWeb;
028import lucee.runtime.customtag.CustomTagUtil;
029import lucee.runtime.customtag.InitFile;
030import lucee.runtime.exp.ExpressionException;
031import lucee.runtime.exp.MissingIncludeException;
032import lucee.runtime.type.util.KeyConstants;
033
034/**
035* Invokes a custom tag for use in CFML application pages.
036**/
037public final class Module extends CFTag {
038
039        @Override
040        public void initFile() throws MissingIncludeException, ExpressionException {
041                ConfigWeb config = pageContext.getConfig();
042        // MUSTMUST cache like ct
043                //String[] filenames=getFileNames(config,getAppendix());// = appendix+'.'+config.getCFMLExtension();
044        
045            Object objTemplate =attributesScope.get(KeyConstants._template,null);
046            Object objName =attributesScope.get(KeyConstants._name,null);
047            source=null;
048            if(objTemplate!=null) {
049                        attributesScope.removeEL(KeyConstants._template);
050                    String template=objTemplate.toString();
051
052            if(StringUtil.startsWith(template,'/'))  {
053                PageSource[] sources = ((PageContextImpl)pageContext).getPageSources(template);
054                PageSource ps = MappingImpl.isOK(sources);
055                
056                if(ps==null)
057                                        throw new MissingIncludeException(sources[0],"could not find template ["+template+"], file ["+sources[0].getDisplayPath()+"] doesn't exist");
058                source=new InitFile(ps,template,template.endsWith('.'+pageContext.getConfig().getCFCExtension()));
059            }
060            else {
061                source=new InitFile(pageContext.getCurrentPageSource().getRealPage(template),template,StringUtil.endsWithIgnoreCase(template,'.'+pageContext.getConfig().getCFCExtension()));
062                if(!MappingImpl.isOK(source.getPageSource())){
063                                        throw new MissingIncludeException(source.getPageSource(),"could not find template ["+template+"], file ["+source.getPageSource().getDisplayPath()+"] doesn't exist");
064                }
065            }
066                
067            //attributesScope.removeEL(TEMPLATE);
068            setAppendix(source.getPageSource());
069            }
070            else if(objName!=null) {
071                        attributesScope.removeEL(KeyConstants._name);
072                String[] filenames = toRelPath(config,objName.toString());
073                boolean exist=false;
074                
075                // appcontext mappings
076                Mapping[] ctms = pageContext.getApplicationContext().getCustomTagMappings(); 
077                if(ctms!=null) {
078                        outer:for(int f=0;f<filenames.length;f++){
079                                for(int i=0;i<ctms.length;i++){
080                                source=new InitFile(ctms[i].getPageSource(filenames[f]),filenames[f],filenames[f].endsWith('.'+config.getCFCExtension()));
081                                if(MappingImpl.isOK(source.getPageSource())) {
082                                        exist=true;
083                                        break outer;
084                                }
085                            }
086                        }
087                }
088                
089                // config mappings
090                if(!exist) {
091                        ctms = config.getCustomTagMappings();
092                        outer:for(int f=0;f<filenames.length;f++){ 
093                            for(int i=0;i<ctms.length;i++){// TODO optimieren siehe CFTag
094                                source=new InitFile(ctms[i].getPageSource(filenames[f]),filenames[f],filenames[f].endsWith('.'+config.getCFCExtension()));
095                                if(MappingImpl.isOK(source.getPageSource())) {
096                                        exist=true;
097                                        break outer;
098                                }
099                            }
100                        }
101                }
102            
103                        if(!exist)
104                                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))+"]");
105                        
106                        setAppendix(source.getPageSource());
107            }
108            else {
109                throw new ExpressionException("you must define attribute template or name for tag module");
110            }
111            
112        }
113
114        private void setAppendix(PageSource source) {
115                String appendix=source.getFileName();
116        int index=appendix.lastIndexOf('.');
117        appendix=appendix.substring(0,index);
118        setAppendix(appendix);
119        }
120
121        /**
122         * translate a dot-notation path to a relpath
123     * @param dotPath
124     * @return relpath
125         * @throws ExpressionException 
126     */
127    private static String[] toRelPath(Config config ,String dotPath) throws ExpressionException {
128        dotPath=dotPath.trim();
129        
130        while(dotPath.indexOf('.')==0) {
131            dotPath=dotPath.substring(1);
132        }
133        int len=-1;
134        while((len=dotPath.length())>0 && dotPath.lastIndexOf('.')==len-1) {
135            dotPath=dotPath.substring(0,len-2);
136        }
137        //dotPath.replace('.','/')+".cfm";
138        return CustomTagUtil.getFileNames(config, dotPath.replace('.','/'));
139    }
140}