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    }