/** * Copyright (c) 2014, the Railo Company Ltd. * Copyright (c) 2015, Lucee Assosication Switzerland * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * */ package lucee.commons.lang; import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import lucee.commons.io.IOUtil; import lucee.commons.io.res.Resource; import lucee.commons.io.res.filter.DirectoryResourceFilter; import lucee.commons.io.res.filter.ExtensionResourceFilter; import lucee.commons.io.res.filter.ResourceFilter; import lucee.runtime.Mapping; import lucee.runtime.MappingImpl; import lucee.runtime.PageContext; import lucee.runtime.PageSource; import lucee.runtime.config.Config; import lucee.runtime.config.ConfigWebUtil; import lucee.runtime.config.Constants; import lucee.runtime.engine.ThreadLocalPageContext; import lucee.transformer.bytecode.util.ASMUtil; import lucee.transformer.bytecode.util.SourceNameClassVisitor.SourceInfo; public class MappingUtil { public static PageSource searchMappingRecursive(Mapping mapping, String name, boolean onlyCFC) { if(name.indexOf('/')==-1) { // TODO handle this as well? Config config = mapping.getConfig(); ExtensionResourceFilter ext =null; if(onlyCFC) ext=new ExtensionResourceFilter(Constants.getComponentExtensions(),true,true); else { ext=new ExtensionResourceFilter(Constants.getExtensions(),true,true); //ext.addExtension(config.getComponentExtension()); } if(mapping.isPhysicalFirst()) { PageSource ps = searchPhysical(mapping,name,ext); if(ps!=null) return ps; ps=searchArchive(mapping,name,onlyCFC); if(ps!=null) return ps; } else { PageSource ps=searchArchive(mapping,name,onlyCFC); if(ps!=null) return ps; ps = searchPhysical(mapping,name,ext); if(ps!=null) return ps; } } return null; } private static PageSource searchArchive(Mapping mapping, String name, boolean onlyCFC) { Resource archive = mapping.getArchive(); if(archive!=null && archive.isFile()) { ZipInputStream zis = null; try{ zis = new ZipInputStream(archive.getInputStream()); ZipEntry entry; Class<?> clazz; while((entry=zis.getNextEntry())!=null){ if(entry.isDirectory() || !entry.getName().endsWith(".class")) continue; clazz=mapping.getArchiveClass(toClassName(entry.getName()),null); if(clazz==null) continue; SourceInfo srcInf = ASMUtil.getSourceInfo(mapping.getConfig(),clazz,onlyCFC); if(name.equalsIgnoreCase(srcInf.name)) { PageSource ps = mapping.getPageSource(srcInf.relativePath); return ps; } } } catch(IOException ioe) { ioe.printStackTrace(); } finally { IOUtil.closeEL(zis); } } // TODO Auto-generated method stub return null; } private static String toClassName(String name) { return name.replace('/', '.').substring(0,name.length()-6); } private static PageSource searchPhysical(Mapping mapping, String name, ResourceFilter filter) { Resource physical = mapping.getPhysical(); if(physical!=null) { String _path=searchPhysical(mapping.getPhysical(), null,name,filter,true); if(_path!=null) { return mapping.getPageSource(_path); } } return null; } private static String searchPhysical(Resource res, String dir,String name, ResourceFilter filter, boolean top) { if(res.isFile()) { if(res.getName().equalsIgnoreCase(name)) { return dir+res.getName(); } } else if(res.isDirectory()) { Resource[] _dir = res.listResources(top?DirectoryResourceFilter.FILTER:filter); if(_dir!=null){ if(dir==null) dir="/"; else dir=dir+res.getName()+"/"; String path; for(int i=0;i<_dir.length;i++){ path=searchPhysical(_dir[i],dir, name,filter,false); if(path!=null) return path; } } } return null; } public static SourceInfo getMatch(PageContext pc, StackTraceElement trace) { return getMatch(pc,null, trace); } public static SourceInfo getMatch(Config config, StackTraceElement trace) { return getMatch(null,config, trace); } public static SourceInfo getMatch(PageContext pc,Config config, StackTraceElement trace) { if(trace.getFileName()==null) return null; if(pc==null && config==null) config=ThreadLocalPageContext.getConfig(); //PageContext pc = ThreadLocalPageContext.get(); Mapping[] mappings = pc!=null? ConfigWebUtil.getAllMappings(pc):ConfigWebUtil.getAllMappings(config); if(pc!=null) config=pc.getConfig(); Mapping mapping; Class clazz; for(int i=0;i<mappings.length;i++){ mapping=mappings[i]; //print.e("virtual:"+mapping.getVirtual()+"+"+trace.getClassName()); // look for the class in that mapping clazz=((MappingImpl)mapping).loadClass(trace.getClassName()); if(clazz==null) continue; // classname is not distinct, because of that we must check class content try { SourceInfo si = ASMUtil.getSourceInfo(config, clazz, false); if(si!=null && trace.getFileName()!=null && trace.getFileName().equals(si.absolutePath(pc))) return si; } catch (IOException e) {} } return null; } }