001 package railo.runtime.functions.component; 002 003 import java.io.File; 004 import java.io.IOException; 005 import java.util.ArrayList; 006 import java.util.HashSet; 007 import java.util.Iterator; 008 import java.util.Set; 009 010 import railo.commons.io.IOUtil; 011 import railo.commons.io.res.Resource; 012 import railo.commons.io.res.filter.ExtensionResourceFilter; 013 import railo.commons.io.res.util.ResourceUtil; 014 import railo.commons.lang.StringUtil; 015 import railo.runtime.Mapping; 016 import railo.runtime.PageContext; 017 import railo.runtime.PageContextImpl; 018 import railo.runtime.PageSource; 019 import railo.runtime.config.ConfigWebImpl; 020 import railo.runtime.exp.ApplicationException; 021 import railo.runtime.exp.PageException; 022 import railo.runtime.ext.function.Function; 023 import railo.runtime.op.Caster; 024 import railo.runtime.type.Array; 025 import railo.runtime.type.ArrayImpl; 026 import railo.runtime.type.util.ArrayUtil; 027 import railo.runtime.type.util.ListUtil; 028 import railo.transformer.bytecode.util.ASMUtil; 029 030 public class ComponentListPackage implements Function { 031 032 private static final long serialVersionUID = 6502632300879457687L; 033 034 private static final ExtensionResourceFilter FILTER_CFC = new ExtensionResourceFilter(".cfc"); 035 private static final ExtensionResourceFilter FILTER_CLASS = new ExtensionResourceFilter(".class"); 036 private static final String[] EMPTY = new String[0]; 037 038 039 public static Array call(PageContext pc , String packageName) throws PageException { 040 Set<String> names; 041 try { 042 names = _call(pc, packageName); 043 } catch (IOException e) { 044 throw Caster.toPageException(e); 045 } 046 047 Array arr=new ArrayImpl(); 048 String name; 049 Iterator<String> it = names.iterator(); 050 while(it.hasNext()){ 051 name=it.next(); 052 if(StringUtil.endsWithIgnoreCase(name, ".cfc")) { 053 name=name.substring(0,name.length()-4); 054 } 055 arr.appendEL(name); 056 } 057 return arr; 058 } 059 060 private static Set<String> _call(PageContext pc , String packageName) throws IOException, ApplicationException { 061 PageContextImpl pci=(PageContextImpl) pc; 062 ConfigWebImpl config = (ConfigWebImpl) pc.getConfig(); 063 Set<String> rtn=null; 064 //var SEP=server.separator.file; 065 066 // get enviroment configuration 067 boolean searchLocal = config.getComponentLocalSearch(); 068 boolean searchRoot=config.getComponentRootSearch(); 069 070 String path=StringUtil.replace(packageName, ".", File.separator, false); 071 072 // search local 073 if(searchLocal) { 074 //Resource dir=pc.getCurrentTemplatePageSource().getResourceTranslated(pc).getParentResource(); 075 //dir=dir.getRealResource(path); 076 PageSource ps= pci.getRelativePageSourceExisting(path); 077 if(ps!=null){ 078 Mapping mapping = ps.getMapping(); 079 String _path=ps.getRealpath(); 080 _path=ListUtil.trim(_path,"\\/"); 081 String[] list = _listMapping(pc,mapping,_path); 082 if(!ArrayUtil.isEmpty(list)) rtn=add(rtn,list); 083 } 084 } 085 086 // check mappings (this includes the webroot) 087 if(searchRoot) { 088 String virtual="/"+StringUtil.replace(packageName, ".", "/", false); 089 Mapping[] mappings = config.getMappings(); 090 Mapping mapping; 091 String _path; 092 String[] list; 093 for(int i=0;i<mappings.length;i++){ 094 mapping=mappings[i]; 095 if(StringUtil.startsWithIgnoreCase(virtual, mapping.getVirtual())) { 096 _path=ListUtil.trim(virtual.substring(mapping.getVirtual().length()),"\\/").trim(); 097 _path=StringUtil.replace(_path, "/", File.separator, false); 098 list = _listMapping(pc,mapping,_path); 099 if(!ArrayUtil.isEmpty(list)) rtn=add(rtn,list); 100 } 101 } 102 } 103 104 // check component mappings 105 Mapping[] mappings = config.getComponentMappings(); 106 Mapping mapping; 107 String[] list; 108 for(int i=0;i<mappings.length;i++){ 109 mapping=mappings[i]; 110 list=_listMapping(pc,mapping,path); 111 if(!ArrayUtil.isEmpty(list)) rtn=add(rtn,list); 112 } 113 114 if(rtn==null)throw new ApplicationException("no package with name ["+packageName+"] found"); 115 return rtn; 116 } 117 118 119 private static Set<String> add(Set<String> set, String[] arr) { 120 if(set==null) set=new HashSet<String>(); 121 for(int i=0;i<arr.length;i++){ 122 set.add(arr[i]); 123 } 124 return set; 125 } 126 127 private static String[] _listMapping(PageContext pc,Mapping mapping, String path) throws IOException{ 128 if(mapping.isPhysicalFirst()) { 129 // check physical 130 String[] list = _listPhysical(path,mapping); 131 if(!ArrayUtil.isEmpty(list)) return list; 132 133 // check archive 134 list=_listArchive(pc,path,mapping); 135 if(!ArrayUtil.isEmpty(list)) return list; 136 } 137 else { 138 // check archive 139 String[] list = _listArchive(pc,path,mapping); 140 if(!ArrayUtil.isEmpty(list)) return list; 141 // check physical 142 list=_listPhysical(path,mapping); 143 if(!ArrayUtil.isEmpty(list)) return list; 144 } 145 return null; 146 } 147 148 private static String[] _listPhysical(String path, Mapping mapping){ 149 Resource physical = mapping.getPhysical(); 150 if(physical!=null) { 151 Resource dir = physical.getRealResource(path); 152 if(dir.isDirectory()) { 153 return dir.list(FILTER_CFC); 154 } 155 } 156 return EMPTY; 157 } 158 159 private static String[] _listArchive(PageContext pc,String path, Mapping mapping) throws IOException { 160 String packageName=StringUtil.replace(path, File.separator, ".", false); 161 Resource archive = mapping.getArchive(); 162 if(archive!=null) { 163 // 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 164 String strDir="zip://"+archive+"!"+File.separator+path; 165 Resource dir = ResourceUtil.toResourceNotExisting(pc, strDir,true); 166 167 if(dir.isDirectory()) { 168 java.util.List<String> list=new ArrayList<String>(); 169 // we use the class files here to get the info, the source files are optional and perhaps not present. 170 Resource[] children = dir.listResources(FILTER_CLASS); 171 String className,c,sourceName=null; 172 for(int i=0;i<children.length;i++){ 173 className=children[i].getName(); 174 className=className.substring(0,className.length()-6); 175 className=packageName+"."+className; 176 177 try { 178 Class<?> clazz = mapping.getClassLoaderForArchive().loadClass(className); 179 sourceName=ASMUtil.getSourceName(clazz); 180 } 181 catch (Throwable t) {} 182 183 if(StringUtil.isEmpty(sourceName)) { 184 c=IOUtil.toString(children[i],null); 185 c=c.substring(0,c.indexOf("<clinit>")); 186 c = ListUtil.last(c, "/\\",true).trim(); 187 if(StringUtil.endsWithIgnoreCase(c, ".cfc")) 188 list.add(c); 189 } 190 else list.add(sourceName); 191 192 } 193 if(list.size()>0) return list.toArray(new String[list.size()]); 194 } 195 } 196 return null; 197 } 198 }