/**
* 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.transformer.bytecode.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import lucee.commons.io.res.filter.ExtensionResourceFilter;
import lucee.commons.lang.StringUtil;
import lucee.runtime.PageContext;
import lucee.runtime.config.Config;
import lucee.runtime.config.Constants;
import lucee.runtime.functions.system.ExpandPath;
import lucee.runtime.type.util.ListUtil;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
public class SourceNameClassVisitor extends ClassVisitor {
private SourceInfo source;
private ExtensionResourceFilter filter;
public SourceNameClassVisitor(Config config, int arg0, boolean onlyCFC) {
super(arg0);
if(onlyCFC) {
filter = new ExtensionResourceFilter(Constants.getComponentExtensions(),true,true);
}
else {
filter = new ExtensionResourceFilter(Constants.getExtensions(),true,true);
//filter.addExtension(config.getComponentExtension());
}
}
@Override
public void visitSource(String source, String debug) {
super.visitSource(source, debug);
if(!StringUtil.isEmpty(source)){
String name=ListUtil.last(source, "/\\");
if(filter.accept(name)) {
// older than 4.2.1.008
if(StringUtil.isEmpty(debug)) {
this.source=new SourceInfo(name,source);
}
else {
//in that case source holds the absolute path
String[] arr=ListUtil.listToStringArray(debug, ';');
String str; int index;
Map<String,String> map=new HashMap<String, String>();
for(int i=0;i<arr.length;i++){
str=arr[i].trim();
index=str.indexOf(':');
if(index==-1) map.put(str.toLowerCase(),"");
else map.put(str.substring(0,index).toLowerCase(),str.substring(index+1));
}
String rel = map.get("rel");
String abs = map.get("abs");
if(StringUtil.isEmpty(abs)) abs=source;
this.source=new SourceInfo(name,rel,abs);
}
}
}
}
public static SourceInfo getSourceInfo(Config config,Class clazz, boolean onlyCFC) throws IOException {
String name = "/"+clazz.getName().replace('.', '/')+".class";
InputStream in=clazz.getResourceAsStream(name);
ClassReader classReader=new ClassReader(in);
SourceNameClassVisitor visitor = new SourceNameClassVisitor(config,4,onlyCFC);
classReader.accept(visitor, 0);
if(visitor.source==null || visitor.source.name==null) return null;
return visitor.source;
}
public static class SourceInfo {
public final String name;
public final String relativePath;
private String absolutePath;
public SourceInfo(String name,String relativePath) {
this(name,relativePath,null);
}
public SourceInfo(String name,String relativePath,String absolutePath) {
this.name=name;
this.relativePath=relativePath;
this.absolutePath=absolutePath;
}
public String absolutePath(PageContext pc) {
if(!StringUtil.isEmpty(absolutePath)) return absolutePath;
try{
absolutePath=ExpandPath.call(pc, relativePath);
}catch(Exception e) {}
return absolutePath;
}
public String toString(){
return new StringBuilder("absolute-path:"+absolutePath+";relative-path:"+relativePath+";name:"+name).toString();
}
}
}