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 }