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.customtag;
020
021import java.util.ArrayList;
022import java.util.Iterator;
023import java.util.List;
024
025import lucee.commons.io.res.Resource;
026import lucee.commons.io.res.util.ResourceUtil;
027import lucee.runtime.Mapping;
028import lucee.runtime.MappingImpl;
029import lucee.runtime.PageContext;
030import lucee.runtime.PageContextImpl;
031import lucee.runtime.PageSource;
032import lucee.runtime.config.Config;
033import lucee.runtime.config.ConfigImpl;
034import lucee.runtime.config.ConfigWeb;
035import lucee.runtime.exp.ExpressionException;
036import lucee.runtime.exp.PageException;
037import lucee.runtime.type.util.ListUtil;
038
039public class CustomTagUtil {
040
041
042        public static InitFile loadInitFile(PageContext pc, String name) throws PageException  {
043                
044                InitFile initFile = loadInitFile(pc, name, null);
045                if(initFile!=null) {
046                return initFile;
047        }
048         // EXCEPTION
049        ConfigWeb config = pc.getConfig();
050        // message
051                StringBuilder msg=new StringBuilder("Custom tag \"").append(getDisplayName(config,name)).append("\" was not found.");
052
053                List<String> dirs = new ArrayList();
054
055                if (config.doLocalCustomTag()) {
056
057                        dirs.add(ResourceUtil.getResource(pc, pc.getCurrentPageSource()).getParent());
058                }
059
060                Mapping[] actms = pc.getApplicationContext().getCustomTagMappings();
061                Mapping[] cctms = config.getCustomTagMappings();
062
063                Resource r;
064
065                if (actms != null) {
066                        for (Mapping m : actms) {
067
068                                r = m.getPhysical();
069                                if (r != null)
070                                        dirs.add(r.toString());
071                        }
072                }
073
074                if (cctms != null) {
075                        for (Mapping m : cctms) {
076
077                                r = m.getPhysical();
078                                if (r != null)
079                                        dirs.add(r.toString());
080                        }
081                }
082
083                if(!dirs.isEmpty()) {
084
085                        msg.append(" Directories searched: ");
086
087                        Iterator<String> it = dirs.iterator();
088                        while (it.hasNext()) {
089
090                                msg.append('"').append(it.next()).append('"');
091                                if (it.hasNext())
092                                        msg.append(", ");
093                        }
094                }
095
096                throw new ExpressionException(msg.toString(),getDetail(config));
097        }
098        
099        public static InitFile loadInitFile(PageContext pc, String name, InitFile defaultValue) throws PageException  {
100        ConfigImpl config=(ConfigImpl) pc.getConfig();
101        String[] filenames=getFileNames(config, name);
102        boolean doCache=config.useCTPathCache();
103        
104        
105        boolean doCustomTagDeepSearch = config.doCustomTagDeepSearch();
106        PageSource ps=null;
107        InitFile initFile;
108    
109   // CACHE
110        // check local
111        String localCacheName=null;    
112        Mapping[] actms = pc.getApplicationContext().getCustomTagMappings();
113        Mapping[] cctms = config.getCustomTagMappings();
114        
115        if(doCache) {
116                if(pc.getConfig().doLocalCustomTag()){
117                        localCacheName=pc.getCurrentPageSource().getDisplayPath().replace('\\', '/');
118                        localCacheName="local:"+localCacheName.substring(0,localCacheName.lastIndexOf('/')+1).concat(name);
119                        initFile=config.getCTInitFile(pc, localCacheName);
120                        if(initFile!=null) return initFile;
121                }
122                
123                // cache application mapping
124                if(actms!=null)for(int i=0;i<actms.length;i++){
125                        initFile=config.getCTInitFile(pc,"application:"+actms[i].hashCode()+"/"+name);
126                        if(initFile!=null)return initFile;
127                }
128                
129                // cache config mapping
130                if(cctms!=null)for(int i=0;i<cctms.length;i++){
131                        initFile=config.getCTInitFile(pc,"config:"+cctms[i].hashCode()+"/"+name);
132                        if(initFile!=null)return initFile;
133                }
134        }
135        
136     // SEARCH
137        // search local
138        if(pc.getConfig().doLocalCustomTag()){
139                    for(int i=0;i<filenames.length;i++){
140                    PageSource[] arr = ((PageContextImpl)pc).getRelativePageSources(filenames[i]);
141                        //ps=pc.getRelativePageSource(filenames[i]);
142                    ps=MappingImpl.isOK(arr);
143                                if(ps !=null) {
144                                        initFile= new InitFile(ps,filenames[i],filenames[i].endsWith('.'+config.getCFCExtension()));
145                                        if(doCache)config.putCTInitFile(localCacheName, initFile);
146                                return initFile;
147                                }
148                }
149        }
150        
151        // search application custom tag mapping
152        if(actms!=null){
153                for(int i=0;i<filenames.length;i++){
154                ps=getMapping(actms, filenames[i],doCustomTagDeepSearch);
155                if(ps!=null) {
156                        initFile=new InitFile(ps,filenames[i],filenames[i].endsWith('.'+config.getCFCExtension()));
157                        if(doCache)config.putCTInitFile("application:"+ps.getMapping().hashCode()+"/"+name, initFile);
158                        return initFile;
159                }
160            }
161        }
162        
163        // search custom tag mappings
164        for(int i=0;i<filenames.length;i++){
165                ps=getMapping(cctms, filenames[i], doCustomTagDeepSearch);
166                if(ps!=null) {
167                        initFile=new InitFile(ps,filenames[i],filenames[i].endsWith('.'+config.getCFCExtension()));
168                        if(doCache)config.putCTInitFile("config:"+ps.getMapping().hashCode()+"/"+name, initFile);
169                        return initFile;
170                }
171        }
172        
173        return defaultValue;
174        }
175        
176        
177        public static String[] getFileNames(Config config, String name) throws ExpressionException {
178                String[] extensions=config.getCustomTagExtensions();
179        if(extensions.length==0) throw new ExpressionException("Custom Tags are disabled");
180        String[] fileNames=new String[extensions.length];
181                
182        for(int i =0;i<fileNames.length;i++){
183                fileNames[i]=name+'.'+extensions[i];
184        }
185        return fileNames;
186        }
187        
188         private static PageSource getMapping(Mapping[] ctms, String filename, boolean doCustomTagDeepSearch) {
189                PageSource ps;
190                for(int i=0;i<ctms.length;i++){
191                        ps = ((MappingImpl) ctms[i]).getCustomTagPath(filename, doCustomTagDeepSearch);
192                                if(ps!=null) return ps;
193                }
194                        return null;
195                }
196         
197         public static  String getDisplayName(Config config,String name) {
198                String[] extensions=config.getCustomTagExtensions();
199        if(extensions.length==0) return name;
200        
201                return name+".["+ListUtil.arrayToList(extensions, "|")+"]";
202        }
203         
204         public static String getDetail(Config config) {
205        boolean hasCFC=false,hasCFML=false;
206        
207        String[] extensions=config.getCustomTagExtensions();
208        for(int i =0;i<extensions.length;i++){
209                if(extensions[i].equalsIgnoreCase(config.getCFCExtension())) hasCFC=true;
210                else hasCFML=true;
211        }
212        StringBuilder sb=new StringBuilder();
213        if(!hasCFC)sb.append("Component based Custom Tags are not enabled;");
214        if(!hasCFML)sb.append("CFML based Custom Tags are not enabled;");
215        return sb.toString();
216        }
217         
218         public static String toString(Mapping[] ctms) {
219                if(ctms==null) return "";
220                StringBuilder sb=new StringBuilder();
221        Resource p;
222        for(int i=0;i<ctms.length;i++){
223                if(sb.length()!=0)sb.append(", ");
224                p = ctms[i].getPhysical();
225                if(p!=null)
226                        sb.append(p.toString());
227        }
228        return sb.toString();
229        }
230}
231
232