1 16 package org.apache.commons.lang.exception; 17 18 import java.io.PrintStream ; 19 import java.io.PrintWriter ; 20 import java.io.Serializable ; 21 import java.io.StringWriter ; 22 import java.util.ArrayList ; 23 import java.util.Arrays ; 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 28 46 public class NestableDelegate implements Serializable { 47 48 51 private transient static final String MUST_BE_THROWABLE = 52 "The Nestable implementation passed to the NestableDelegate(Nestable) " 53 + "constructor must extend java.lang.Throwable"; 54 55 60 private Throwable nestable = null; 61 62 70 public static boolean topDown = true; 71 72 80 public static boolean trimStackFrames = true; 81 82 90 public static boolean matchSubclasses = true; 91 92 100 public NestableDelegate(Nestable nestable) { 101 if (nestable instanceof Throwable ) { 102 this.nestable = (Throwable ) nestable; 103 } else { 104 throw new IllegalArgumentException (MUST_BE_THROWABLE); 105 } 106 } 107 108 121 public String getMessage(int index) { 122 Throwable t = this.getThrowable(index); 123 if (Nestable.class.isInstance(t)) { 124 return ((Nestable) t).getMessage(0); 125 } else { 126 return t.getMessage(); 127 } 128 } 129 130 143 public String getMessage(String baseMsg) { 144 StringBuffer msg = new StringBuffer (); 145 if (baseMsg != null) { 146 msg.append(baseMsg); 147 } 148 149 Throwable nestedCause = ExceptionUtils.getCause(this.nestable); 150 if (nestedCause != null) { 151 String causeMsg = nestedCause.getMessage(); 152 if (causeMsg != null) { 153 if (baseMsg != null) { 154 msg.append(": "); 155 } 156 msg.append(causeMsg); 157 } 158 159 } 160 return msg.length() > 0 ? msg.toString() : null; 161 } 162 163 174 public String [] getMessages() { 175 Throwable [] throwables = this.getThrowables(); 176 String [] msgs = new String [throwables.length]; 177 for (int i = 0; i < throwables.length; i++) { 178 msgs[i] = 179 (Nestable.class.isInstance(throwables[i]) 180 ? ((Nestable) throwables[i]).getMessage(0) 181 : throwables[i].getMessage()); 182 } 183 return msgs; 184 } 185 186 198 public Throwable getThrowable(int index) { 199 if (index == 0) { 200 return this.nestable; 201 } 202 Throwable [] throwables = this.getThrowables(); 203 return throwables[index]; 204 } 205 206 213 public int getThrowableCount() { 214 return ExceptionUtils.getThrowableCount(this.nestable); 215 } 216 217 225 public Throwable [] getThrowables() { 226 return ExceptionUtils.getThrowables(this.nestable); 227 } 228 229 253 public int indexOfThrowable(Class type, int fromIndex) { 254 if (type == null) { 255 return -1; 256 } 257 if (fromIndex < 0) { 258 throw new IndexOutOfBoundsException ("The start index was out of bounds: " + fromIndex); 259 } 260 Throwable [] throwables = ExceptionUtils.getThrowables(this.nestable); 261 if (fromIndex >= throwables.length) { 262 throw new IndexOutOfBoundsException ("The start index was out of bounds: " 263 + fromIndex + " >= " + throwables.length); 264 } 265 if (matchSubclasses) { 266 for (int i = fromIndex; i < throwables.length; i++) { 267 if (type.isAssignableFrom(throwables[i].getClass())) { 268 return i; 269 } 270 } 271 } else { 272 for (int i = fromIndex; i < throwables.length; i++) { 273 if (type.equals(throwables[i].getClass())) { 274 return i; 275 } 276 } 277 } 278 return -1; 279 } 280 281 285 public void printStackTrace() { 286 printStackTrace(System.err); 287 } 288 289 296 public void printStackTrace(PrintStream out) { 297 synchronized (out) { 298 PrintWriter pw = new PrintWriter (out, false); 299 printStackTrace(pw); 300 pw.flush(); 302 } 303 } 304 305 316 public void printStackTrace(PrintWriter out) { 317 Throwable throwable = this.nestable; 318 if (ExceptionUtils.isThrowableNested()) { 320 if (throwable instanceof Nestable) { 321 ((Nestable)throwable).printPartialStackTrace(out); 322 } else { 323 throwable.printStackTrace(out); 324 } 325 return; 326 } 327 328 List stacks = new ArrayList (); 330 while (throwable != null) { 331 String [] st = getStackFrames(throwable); 332 stacks.add(st); 333 throwable = ExceptionUtils.getCause(throwable); 334 } 335 336 String separatorLine = "Caused by: "; 338 if (!topDown) { 339 separatorLine = "Rethrown as: "; 340 Collections.reverse(stacks); 341 } 342 343 if (trimStackFrames) { 345 trimStackFrames(stacks); 346 } 347 348 synchronized (out) { 349 for (Iterator iter=stacks.iterator(); iter.hasNext();) { 350 String [] st = (String []) iter.next(); 351 for (int i=0, len=st.length; i < len; i++) { 352 out.println(st[i]); 353 } 354 if (iter.hasNext()) { 355 out.print(separatorLine); 356 } 357 } 358 } 359 } 360 361 370 protected String [] getStackFrames(Throwable t) { 371 StringWriter sw = new StringWriter (); 372 PrintWriter pw = new PrintWriter (sw, true); 373 374 if (t instanceof Nestable) { 376 ((Nestable) t).printPartialStackTrace(pw); 377 } else { 378 t.printStackTrace(pw); 379 } 380 return ExceptionUtils.getStackFrames(sw.getBuffer().toString()); 381 } 382 383 391 protected void trimStackFrames(List stacks) { 392 for (int size=stacks.size(), i=size-1; i > 0; i--) { 393 String [] curr = (String []) stacks.get(i); 394 String [] next = (String []) stacks.get(i-1); 395 396 List currList = new ArrayList (Arrays.asList(curr)); 397 List nextList = new ArrayList (Arrays.asList(next)); 398 ExceptionUtils.removeCommonFrames(currList, nextList); 399 400 int trimmed = curr.length - currList.size(); 401 if (trimmed > 0) { 402 currList.add("\t... "+trimmed+" more"); 403 stacks.set( 404 i, 405 currList.toArray(new String [currList.size()]) 406 ); 407 } 408 } 409 } 410 } 411 | Popular Tags |