package railo.runtime.functions.component; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import railo.commons.io.IOUtil; import railo.commons.io.res.Resource; import railo.commons.io.res.filter.ExtensionResourceFilter; import railo.commons.io.res.util.ResourceUtil; import railo.commons.lang.StringUtil; import railo.runtime.Mapping; import railo.runtime.PageContext; import railo.runtime.PageContextImpl; import railo.runtime.PageSource; import railo.runtime.config.ConfigWebImpl; import railo.runtime.exp.ApplicationException; import railo.runtime.exp.PageException; import railo.runtime.ext.function.Function; import railo.runtime.op.Caster; import railo.runtime.type.Array; import railo.runtime.type.ArrayImpl; import railo.runtime.type.util.ArrayUtil; import railo.runtime.type.util.ListUtil; import railo.transformer.bytecode.util.ASMUtil; public class ComponentListPackage implements Function { private static final long serialVersionUID = 6502632300879457687L; private static final ExtensionResourceFilter FILTER_CFC = new ExtensionResourceFilter(".cfc"); private static final ExtensionResourceFilter FILTER_CLASS = new ExtensionResourceFilter(".class"); private static final String[] EMPTY = new String[0]; public static Array call(PageContext pc , String packageName) throws PageException { Set<String> names; try { names = _call(pc, packageName); } catch (IOException e) { throw Caster.toPageException(e); } Array arr=new ArrayImpl(); String name; Iterator<String> it = names.iterator(); while(it.hasNext()){ name=it.next(); if(StringUtil.endsWithIgnoreCase(name, ".cfc")) { name=name.substring(0,name.length()-4); } arr.appendEL(name); } return arr; } private static Set<String> _call(PageContext pc , String packageName) throws IOException, ApplicationException { PageContextImpl pci=(PageContextImpl) pc; ConfigWebImpl config = (ConfigWebImpl) pc.getConfig(); Set<String> rtn=null; //var SEP=server.separator.file; // get enviroment configuration boolean searchLocal = config.getComponentLocalSearch(); boolean searchRoot=config.getComponentRootSearch(); String path=StringUtil.replace(packageName, ".", File.separator, false); // search local if(searchLocal) { //Resource dir=pc.getCurrentTemplatePageSource().getResourceTranslated(pc).getParentResource(); //dir=dir.getRealResource(path); PageSource ps= pci.getRelativePageSourceExisting(path); if(ps!=null){ Mapping mapping = ps.getMapping(); String _path=ps.getRealpath(); _path=ListUtil.trim(_path,"\\/"); String[] list = _listMapping(pc,mapping,_path); if(!ArrayUtil.isEmpty(list)) rtn=add(rtn,list); } } // check mappings (this includes the webroot) if(searchRoot) { String virtual="/"+StringUtil.replace(packageName, ".", "/", false); Mapping[] mappings = config.getMappings(); Mapping mapping; String _path; String[] list; for(int i=0;i<mappings.length;i++){ mapping=mappings[i]; if(StringUtil.startsWithIgnoreCase(virtual, mapping.getVirtual())) { _path=ListUtil.trim(virtual.substring(mapping.getVirtual().length()),"\\/").trim(); _path=StringUtil.replace(_path, "/", File.separator, false); list = _listMapping(pc,mapping,_path); if(!ArrayUtil.isEmpty(list)) rtn=add(rtn,list); } } } // check component mappings Mapping[] mappings = config.getComponentMappings(); Mapping mapping; String[] list; for(int i=0;i<mappings.length;i++){ mapping=mappings[i]; list=_listMapping(pc,mapping,path); if(!ArrayUtil.isEmpty(list)) rtn=add(rtn,list); } if(rtn==null)throw new ApplicationException("no package with name ["+packageName+"] found"); return rtn; } private static Set<String> add(Set<String> set, String[] arr) { if(set==null) set=new HashSet<String>(); for(int i=0;i<arr.length;i++){ set.add(arr[i]); } return set; } private static String[] _listMapping(PageContext pc,Mapping mapping, String path) throws IOException{ if(mapping.isPhysicalFirst()) { // check physical String[] list = _listPhysical(path,mapping); if(!ArrayUtil.isEmpty(list)) return list; // check archive list=_listArchive(pc,path,mapping); if(!ArrayUtil.isEmpty(list)) return list; } else { // check archive String[] list = _listArchive(pc,path,mapping); if(!ArrayUtil.isEmpty(list)) return list; // check physical list=_listPhysical(path,mapping); if(!ArrayUtil.isEmpty(list)) return list; } return null; } private static String[] _listPhysical(String path, Mapping mapping){ Resource physical = mapping.getPhysical(); if(physical!=null) { Resource dir = physical.getRealResource(path); if(dir.isDirectory()) { return dir.list(FILTER_CFC); } } return EMPTY; } private static String[] _listArchive(PageContext pc,String path, Mapping mapping) throws IOException { String packageName=StringUtil.replace(path, File.separator, ".", false); Resource archive = mapping.getArchive(); if(archive!=null) { // TODO nor working with pathes with none ascci characters, eith none ascci characters, the java class path is renamed, so make sure you rename the path as well String strDir="zip://"+archive+"!"+File.separator+path; Resource dir = ResourceUtil.toResourceNotExisting(pc, strDir,true); if(dir.isDirectory()) { java.util.List<String> list=new ArrayList<String>(); // we use the class files here to get the info, the source files are optional and perhaps not present. Resource[] children = dir.listResources(FILTER_CLASS); String className,c,sourceName=null; for(int i=0;i<children.length;i++){ className=children[i].getName(); className=className.substring(0,className.length()-6); className=packageName+"."+className; try { Class<?> clazz = mapping.getClassLoaderForArchive().loadClass(className); sourceName=ASMUtil.getSourceName(clazz); } catch (Throwable t) {} if(StringUtil.isEmpty(sourceName)) { c=IOUtil.toString(children[i],(Charset)null); int loc = c.indexOf("<clinit>"); if(loc !=-1) { c=c.substring(0,loc); c = ListUtil.last(c, "/\\",true).trim(); if(StringUtil.endsWithIgnoreCase(c, ".cfc")) list.add(c); } } else list.add(sourceName); } if(list.size()>0) return list.toArray(new String[list.size()]); } } return null; } }