001 // Copyright 2008, 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.ioc.util; 016 017 import org.apache.tapestry5.ioc.services.ClassPropertyAdapter; 018 import org.apache.tapestry5.ioc.services.PropertyAccess; 019 020 /** 021 * Contains static methods useful for manipulating exceptions. 022 */ 023 public class ExceptionUtils 024 { 025 /** 026 * Locates a particular type of exception, working its way via the cause property of each exception in the exception 027 * stack. 028 * 029 * @param t the outermost exception 030 * @param type the type of exception to search for 031 * @return the first exception of the given type, if found, or null 032 */ 033 public static <T extends Throwable> T findCause(Throwable t, Class<T> type) 034 { 035 Throwable current = t; 036 037 while (current != null) 038 { 039 if (type.isInstance(current)) 040 { 041 return type.cast(current); 042 } 043 044 // Not a match, work down. 045 046 current = current.getCause(); 047 } 048 049 return null; 050 } 051 052 /** 053 * Locates a particular type of exception, working its way down via any property that returns some type of Exception. 054 * This is more expensive, but more accurate, than {@link #findCause(Throwable, Class)} as it works with older exceptions 055 * that do not properly implement the (relatively new) {@linkplain Throwable#getCause() cause property}. 056 * 057 * @param t the outermost exception 058 * @param type the type of exception to search for 059 * @param access used to access properties 060 * @return the first exception of the given type, if found, or null 061 */ 062 public static <T extends Throwable> T findCause(Throwable t, Class<T> type, PropertyAccess access) 063 { 064 Throwable current = t; 065 066 while (current != null) 067 { 068 if (type.isInstance(current)) 069 { 070 return type.cast(current); 071 } 072 073 Throwable next = null; 074 075 ClassPropertyAdapter adapter = access.getAdapter(current); 076 077 for (String name : adapter.getPropertyNames()) 078 { 079 080 Object value = adapter.getPropertyAdapter(name).get(current); 081 082 if (value != null && value != current && value instanceof Throwable) 083 { 084 next = (Throwable) value; 085 break; 086 } 087 } 088 089 current = next; 090 } 091 092 093 return null; 094 } 095 }