/**
* Copyright (c) 2015, Lucee Assosication Switzerland. 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.orm;
import java.lang.reflect.Method;
import lucee.commons.lang.ExceptionUtil;
import lucee.loader.engine.CFMLEngineFactory;
import lucee.runtime.Component;
import lucee.runtime.db.DataSource;
import lucee.runtime.exp.PageException;
import lucee.runtime.type.Collection.Key;
import lucee.runtime.type.util.KeyConstants;
import lucee.runtime.type.util.ListUtil;
public class ORMExceptionUtil {
private static Method setAdditional;
public static PageException createException(ORMSession session,Component cfc,Throwable t) {
PageException pe = CFMLEngineFactory.getInstance().getExceptionUtil().createApplicationException(t.getMessage());
pe.setStackTrace(t.getStackTrace());
if(session!=null)setAddional(session,pe);
if(cfc!=null)setContext(pe,cfc);
return pe;
}
public static PageException createException(ORMSession session,Component cfc,String message,String detail) {
PageException pe = CFMLEngineFactory.getInstance().getExceptionUtil().createApplicationException(message);
if(session!=null)setAddional(session,pe);
if(cfc!=null)setContext(pe,cfc);
return pe;
}
private static void setContext(PageException pe,Component cfc) {
if(cfc!=null && getPageDeep(pe)==0)pe.addContext(cfc.getPageSource(), 1, 1, null);
}
private static void setAddional(ORMSession session,PageException pe) {
String[] names = session.getEntityNames();
setAdditional(pe, KeyConstants._Entities, ListUtil.arrayToList(names, ", "));
setAddional(pe,session.getDataSources());
}
private static void setAddional(PageException pe,DataSource... sources) {
if(sources!=null && sources.length>0){
StringBuilder sb=new StringBuilder();
for(int i=0;i<sources.length;i++){
if(i>0) sb.append(", ");
sb.append(sources[i].getName());
}
setAdditional(pe, KeyConstants._Datasource, sb.toString());
}
}
private static int getPageDeep(PageException pe) {
StackTraceElement[] traces = getStackTraceElements(pe);
String template="",tlast;
StackTraceElement trace=null;
int index=0;
for(int i=0;i<traces.length;i++) {
trace=traces[i];
tlast=template;
template=trace.getFileName();
if(trace.getLineNumber()<=0 || template==null || CFMLEngineFactory.getInstance().getResourceUtil().getExtension(template,"").equals("java")) continue;
if(!(tlast==null?"":tlast).equals(template))index++;
}
return index;
}
private static StackTraceElement[] getStackTraceElements(Throwable t) {
StackTraceElement[] st=getStackTraceElements(t,true);
if(st==null) st= getStackTraceElements(t,false);
return st;
}
private static StackTraceElement[] getStackTraceElements(Throwable t, boolean onlyWithCML) {
StackTraceElement[] st;
Throwable cause=t.getCause();
if(cause!=null){
st = getStackTraceElements(cause,onlyWithCML);
if(st!=null) return st;
}
st=t.getStackTrace();
if(!onlyWithCML || hasCFMLinStacktrace(st)){
return st;
}
return null;
}
private static boolean hasCFMLinStacktrace(StackTraceElement[] traces) {
for(int i=0;i<traces.length;i++) {
if(traces[i].getFileName()!=null && !traces[i].getFileName().endsWith(".java")) return true;
}
return false;
}
public static void setAdditional(PageException pe, Key name, Object value) {
try{
if(setAdditional==null || setAdditional.getDeclaringClass()!=pe.getClass()) {
setAdditional=pe.getClass().getMethod("setAdditional", new Class[]{Key.class,Object.class});
}
setAdditional.invoke(pe, new Object[]{name,value});
}
catch(Throwable t) {ExceptionUtil.rethrowIfNecessary(t);}
}
}