/** * * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. * * 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.runtime.functions.system; import java.util.Iterator; import lucee.commons.io.res.Resource; import lucee.commons.io.res.util.ResourceUtil; import lucee.commons.lang.ExceptionUtil; import lucee.runtime.PageContext; import lucee.runtime.PageContextImpl; import lucee.runtime.PageSource; import lucee.runtime.config.ConfigWeb; import lucee.runtime.converter.JSONConverter; import lucee.runtime.exp.FunctionException; import lucee.runtime.exp.PageException; import lucee.runtime.ext.function.Function; import lucee.runtime.op.Caster; import lucee.runtime.type.Array; import lucee.runtime.type.ArrayImpl; import lucee.runtime.type.Collection; import lucee.runtime.type.KeyImpl; import lucee.runtime.type.Struct; import lucee.runtime.type.StructImpl; import lucee.runtime.type.UDF; import lucee.runtime.type.util.KeyConstants; /** * returns the root of this actuell Page Context */ public final class CallStackGet implements Function { private static final long serialVersionUID = -5853145189662102420L; static final Collection.Key LINE_NUMBER = KeyImpl.init("LineNumber"); public static Object call(PageContext pc) { Array arr=new ArrayImpl(); _getTagContext(pc, arr, new Exception("Stack trace"),LINE_NUMBER); return arr; } public static Object call(PageContext pc, String type) throws PageException { Array arr = (Array)call(pc); if ( type.equalsIgnoreCase( "array" ) ) return arr; if ( type.equalsIgnoreCase( "json" ) ) { try { return new JSONConverter(true,null).serialize( pc, arr, false ); } catch(Throwable t) { ExceptionUtil.rethrowIfNecessary(t); throw Caster.toPageException( t ); } } StringBuilder sb = new StringBuilder( 64 * arr.size() ); Struct struct; String func; Iterator it = arr.valueIterator(); if ( type.equalsIgnoreCase( "text" ) || type.equalsIgnoreCase( "string" ) ) { while (it.hasNext()) { struct = (Struct)it.next(); sb.append( (String)struct.get( KeyConstants._template ) ); func = (String)struct.get( KeyConstants._function ); if ( !func.isEmpty() ) { sb.append( '.' ).append( func ).append( "()" ); } sb.append( ':' ).append( ((Double)struct.get( LINE_NUMBER )).intValue() ); if ( it.hasNext() ) sb.append( "; " ); } return sb.toString(); } if ( type.equalsIgnoreCase( "html" ) ) { sb.append( "<ul class='-lucee-array'>" ); while (it.hasNext()) { struct = (Struct)it.next(); sb.append( "<li>" ); sb.append( (String)struct.get( KeyConstants._template ) ); func = (String)struct.get( KeyConstants._function ); if ( !func.isEmpty() ) { sb.append( '.' ).append( func ).append( "()" ); } sb.append( ':' ).append( ((Double)struct.get( LINE_NUMBER )).intValue() ); sb.append( "</li>" ); } sb.append("</ul>"); return sb.toString(); } throw new FunctionException( pc, CallStackGet.class.getSimpleName(), 1, "type", "Argument type [" + type +"] is not valid. Valid types are: [array], text, html, json." ); } public static void _getTagContext(PageContext pc, Array tagContext, Throwable t,Collection.Key lineNumberName) { //Throwable root = t.getRootCause(); Throwable cause = t.getCause(); if(cause!=null)_getTagContext(pc, tagContext, cause,lineNumberName); StackTraceElement[] traces = t.getStackTrace(); UDF[] udfs = ((PageContextImpl)pc).getUDFs(); int line=0; String template; Struct item; StackTraceElement trace=null; String functionName,methodName; int index=udfs.length-1; for(int i=0;i<traces.length;i++) { trace=traces[i]; template=trace.getFileName(); if(trace.getLineNumber()<=0 || template==null || ResourceUtil.getExtension(template,"").equals("java")) continue; methodName=trace.getMethodName(); if(methodName!=null && methodName.startsWith("udfCall") && index>-1) functionName=udfs[index--].getFunctionName(); else functionName=""; item=new StructImpl(); line=trace.getLineNumber(); item.setEL(KeyConstants._function,functionName); /* template is now a absolute path try { template=ExpandPath.call(pc, template); } catch (PageException e) {}*/ item.setEL(KeyConstants._template,abs((PageContextImpl)pc,template)); item.setEL(lineNumberName,new Double(line)); tagContext.appendEL(item); } } private static String abs(PageContextImpl pc, String template) { ConfigWeb config = pc.getConfig(); Resource res = config.getResource(template); if(res.exists()) return template; PageSource ps = pc==null?null:pc.getPageSource(template); res = ps==null?null:ps.getPhyscalFile(); if(res==null || !res.exists()) { res=config.getResource(ps.getDisplayPath()); if(res!=null && res.exists()) return res.getAbsolutePath(); } else return res.getAbsolutePath(); return template; } }