001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.commons.lang; 020 021import java.io.IOException; 022import java.io.PrintWriter; 023import java.io.StringWriter; 024import java.lang.reflect.InvocationTargetException; 025import java.util.Arrays; 026import java.util.Iterator; 027 028import lucee.runtime.exp.NativeException; 029import lucee.runtime.exp.PageException; 030import lucee.runtime.exp.PageExceptionImpl; 031import lucee.runtime.type.Collection; 032import lucee.runtime.type.util.CollectionUtil; 033import lucee.runtime.type.util.KeyConstants; 034import lucee.runtime.type.util.ListUtil; 035 036public final class ExceptionUtil { 037 038 public static String getStacktrace(Throwable t, boolean addMessage) { 039 StringWriter sw = new StringWriter(); 040 PrintWriter pw = new PrintWriter(sw); 041 t.printStackTrace(pw); 042 pw.close(); 043 String st = sw.toString(); 044 String msg=t.getMessage(); 045 if(addMessage && !StringUtil.isEmpty(msg) && !st.startsWith(msg.trim())) 046 st=msg+"\n"+st; 047 return st; 048 049 } 050 051 052 public static String getMessage(Throwable t) { 053 String msg=t.getMessage(); 054 if(StringUtil.isEmpty(msg,true)) msg=t.getClass().getName(); 055 056 StringBuilder sb=new StringBuilder(msg); 057 058 if(t instanceof PageException){ 059 PageException pe=(PageException)t; 060 String detail = pe.getDetail(); 061 if(!StringUtil.isEmpty(detail,true)) { 062 sb.append('\n'); 063 sb.append(detail); 064 } 065 } 066 return sb.toString(); 067 } 068 069 public static PageException addHint(PageExceptionImpl pe,String hint) { 070 pe.setAdditional(KeyConstants._Hint, hint); 071 return pe; 072 } 073 074 075 /** 076 * creates a message for key not found with soundex check for similar key 077 * @param keys 078 * @param keyLabel 079 * @return 080 */ 081 public static String similarKeyMessage(Collection.Key[] _keys,String keySearched, String keyLabel, String keyLabels, boolean listAll) { 082 boolean empty=_keys.length==0; 083 if(listAll && (_keys.length>50 || empty)) { 084 listAll=false; 085 } 086 087 String list=null; 088 if(listAll) { 089 Arrays.sort(_keys); 090 list=ListUtil.arrayToList(_keys, ","); 091 } 092 String keySearchedSoundex=StringUtil.soundex(keySearched); 093 094 for(int i=0;i<_keys.length;i++){ 095 if(StringUtil.soundex(_keys[i].getString()).equals(keySearchedSoundex)) { 096 String appendix; 097 if(listAll) appendix=". Here is a complete list of all available "+keyLabels+": ["+list+"]."; 098 else if(empty) appendix=". The structure is empty"; 099 else appendix="."; 100 101 return "The "+keyLabel+" ["+keySearched+"] does not exist, but there is a similar "+keyLabel+" with name ["+_keys[i].getString()+"] available"+appendix; 102 } 103 } 104 String appendix; 105 if(listAll) appendix=", only the following "+keyLabels+" are available: ["+list+"]."; 106 else if(empty) appendix=", the structure is empty"; 107 else appendix="."; 108 return "The "+keyLabel+" ["+keySearched+"] does not exist"+appendix; 109 } 110 111 112 public static String similarKeyMessage(Collection coll,String keySearched, String keyLabel, String keyLabels, boolean listAll) { 113 return similarKeyMessage(CollectionUtil.keys(coll), keySearched, keyLabel, keyLabels,listAll); 114 } 115 116 public static IOException toIOException(Throwable t) { 117 ExceptionUtil.rethrowIfNecessary(t); 118 if(t instanceof IOException) return (IOException) t; 119 if(t instanceof InvocationTargetException) return toIOException(((InvocationTargetException) t).getCause()); 120 if(t instanceof NativeException) return toIOException(((NativeException)t).getCause()); 121 122 IOException ioe = new IOException(t.getClass().getName()+":"+t.getMessage()); 123 ioe.setStackTrace(t.getStackTrace()); 124 return ioe; 125 } 126 127 128 public static String createSoundexDetail(String name, Iterator<String> it, String keyName) { 129 StringBuilder sb=new StringBuilder(); 130 String k ,sname=StringUtil.soundex(name); 131 while(it.hasNext()){ 132 k = it.next(); 133 if(StringUtil.soundex(k).equals(sname)) 134 return "did you mean ["+k+"]"; 135 if(sb.length()!=0)sb.append(','); 136 sb.append(k); 137 } 138 return "available "+keyName+" are ["+sb+"]"; 139 } 140 141 public static RuntimeException toRuntimeException(Throwable t) { 142 ExceptionUtil.rethrowIfNecessary(t); 143 return new RuntimeException(t); 144 } 145 146 public static void rethrowIfNecessary(Throwable t) { 147 if(t instanceof ThreadDeath) throw (ThreadDeath)t; // never catch this rethrow 148 } 149}