/**
* 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.commons.lang;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Iterator;
import lucee.runtime.exp.NativeException;
import lucee.runtime.exp.PageException;
import lucee.runtime.exp.PageExceptionImpl;
import lucee.runtime.type.Collection;
import lucee.runtime.type.util.CollectionUtil;
import lucee.runtime.type.util.KeyConstants;
import lucee.runtime.type.util.ListUtil;
public final class ExceptionUtil {
public static String getStacktrace(Throwable t, boolean addMessage) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw);
pw.close();
String st = sw.toString();
String msg=t.getMessage();
if(addMessage && !StringUtil.isEmpty(msg) && !st.startsWith(msg.trim()))
st=msg+"\n"+st;
return st;
}
public static String getMessage(Throwable t) {
String msg=t.getMessage();
if(StringUtil.isEmpty(msg,true)) msg=t.getClass().getName();
StringBuilder sb=new StringBuilder(msg);
if(t instanceof PageException){
PageException pe=(PageException)t;
String detail = pe.getDetail();
if(!StringUtil.isEmpty(detail,true)) {
sb.append('\n');
sb.append(detail);
}
}
return sb.toString();
}
public static PageException addHint(PageExceptionImpl pe,String hint) {
pe.setAdditional(KeyConstants._Hint, hint);
return pe;
}
/**
* creates a message for key not found with soundex check for similar key
* @param keys
* @param keyLabel
* @return
*/
public static String similarKeyMessage(Collection.Key[] _keys,String keySearched, String keyLabel, String keyLabels,String in, boolean listAll) {
String inThe=StringUtil.isEmpty(in,true)?"":" in the "+in;
boolean empty=_keys.length==0;
if(listAll && (_keys.length>50 || empty)) {
listAll=false;
}
String list=null;
if(listAll) {
Arrays.sort(_keys);
list=ListUtil.arrayToList(_keys, ",");
}
String keySearchedSoundex=StringUtil.soundex(keySearched);
for(int i=0;i<_keys.length;i++){
if(StringUtil.soundex(_keys[i].getString()).equals(keySearchedSoundex)) {
String appendix;
if(listAll) appendix=". Here is a complete list of all available "+keyLabels+": ["+list+"].";
else if(empty) appendix=". The structure is empty";
else appendix=".";
return "The "+keyLabel+" ["+keySearched+"] does not exist "+inThe+", but there is a similar "+keyLabel+" with name ["+_keys[i].getString()+"] available"+appendix;
}
}
String appendix;
if(listAll) appendix=", only the following "+keyLabels+" are available: ["+list+"].";
else if(empty) appendix=", the structure is empty";
else appendix=".";
return "The "+keyLabel+" ["+keySearched+"] does not exist"+inThe+appendix;
}
public static String similarKeyMessage(Collection coll,String keySearched, String keyLabel, String keyLabels, String in, boolean listAll) {
return similarKeyMessage(CollectionUtil.keys(coll), keySearched, keyLabel, keyLabels,in,listAll);
}
public static IOException toIOException(Throwable t) {
rethrowIfNecessary(t);
if(t instanceof IOException) return (IOException) t;
if(t instanceof InvocationTargetException) return toIOException(((InvocationTargetException) t).getCause());
if(t instanceof NativeException) return toIOException(((NativeException)t).getCause());
IOException ioe = new IOException(t.getClass().getName()+":"+t.getMessage());
ioe.setStackTrace(t.getStackTrace());
return ioe;
}
public static String createSoundexDetail(String name, Iterator<String> it, String keyName) {
StringBuilder sb=new StringBuilder();
String k ,sname=StringUtil.soundex(name);
while(it.hasNext()){
k = it.next();
if(StringUtil.soundex(k).equals(sname))
return "did you mean ["+k+"]";
if(sb.length()!=0)sb.append(',');
sb.append(k);
}
return "available "+keyName+" are ["+sb+"]";
}
public static RuntimeException toRuntimeException(Throwable t) {
rethrowIfNecessary(t);
// TODO is there a improvement necessary?
return new RuntimeException(t);
}
private static Throwable unwrap(Throwable t) {
if(t instanceof NativeException) return unwrap(((NativeException)t).getException());
Throwable cause = t.getCause();
if(cause!=null && cause!=t) return unwrap(cause);
return t;
}
public static void rethrowIfNecessary(Throwable t) {
if(unwrap(t) instanceof ThreadDeath) throw (ThreadDeath)t; // never catch this rethrow
}
}