1 /* 2 * Copyright the original author or authors. 3 * 4 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.mozilla.org/MPL/MPL-1.1.html 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import org.as2lib.core.BasicClass; 18 import org.as2lib.util.Stringifier; 19 import org.as2lib.util.StringUtil; 20 import org.as2lib.env.except.Throwable; 21 import org.as2lib.env.except.StackTraceElement; 22 import org.as2lib.env.reflect.ReflectUtil; 23 24 /** 25 * {@code ThrowableStringifier} stringifies instances of type {@link Throwable}. 26 * 27 * @author Simon Wacker 28 */ 29 class org.as2lib.env.except.ThrowableStringifier extends BasicClass implements Stringifier { 30 31 /** Show the stack trace. */ 32 private var showStackTrace:Boolean; 33 34 /** Show the cause. */ 35 private var showCause:Boolean; 36 37 /** 38 * Constructs a new {@code ThrowableStringifier} instance. 39 * 40 * <p>You can switch different parts of the string representation on or off using 41 * the declared arguments. 42 * 43 * <p>The stack trace and the cause are be default shown. That means if you want 44 * them to be contained in the resulting string representation you do not have to 45 * specify any arguments. 46 * 47 * <p>The settings apply only to the throwable to stringify. That means they do 48 * not apply for its cause. The cause is responsible for stringifying itself. 49 * 50 * @param showStackTrace determines whether the string representation contains the 51 * stack trace 52 * @param showCause determines whether the string representation contains the 53 * cause 54 */ 55 public function ThrowableStringifier(showStackTrace:Boolean, showCause:Boolean) { 56 this.showStackTrace = showStackTrace == null ? true : showStackTrace; 57 this.showCause = showCause == null ? true : showCause; 58 } 59 60 /** 61 * Returns a string representation of the passed-in {@link Throwable} instance. 62 * 63 * <p>Depending on the settings you made on instantiation the stack trace and 64 * cause is contained in the resulting string or not. 65 * 66 * <p>Note that the cause is stringified by its own stringifier. That means the 67 * setting show stack trace and show cause settings apply only for this throwable 68 * and not for its causes. The cause is responsible for stringifying itself. 69 * 70 * <p>The throwable elements are also responsible for stringifying themselves. 71 * 72 * <p>The string representation is composed as follows: 73 * <pre> 74 * theFullQualifiedNameOfTheThrowable: theMessage 75 * at theStringRepresentationOfTheStackTraceElement 76 * .. 77 * Caused by: theStringRepresentationOfTheCause 78 * </pre> 79 * 80 * <p>Here is how a real string representation could look like: 81 * <pre> 82 * org.as2lib.data.holder.IllegalLengthException: The argument length '-2' is not allowed to be negative. 83 * at org.as2lib.data.holder.MyDataHolder.setMaximumLength(Number) 84 * Caused by: org.as2lib.data.math.IllegalNumberException: The argument number '-2' is not allowed in a range from 0 to ∞. 85 * at org.as2lib.data.math.Range.setNumber(Number) 86 * </pre> 87 * 88 * @param target the {@code Throwable} to stringify 89 * @return the string representation of the passed-in {@code target} throwable 90 * @see #stringifyStackTrace 91 */ 92 public function execute(target):String { 93 var throwable:Throwable = target; 94 var result:String = ""; 95 var typeName:String = ReflectUtil.getTypeNameForInstance(throwable); 96 var indent:Number = typeName.length + 2; 97 result += typeName + ": " + StringUtil.addSpaceIndent(throwable.getMessage(), indent).substr(indent); 98 var stackTrace:Array = throwable.getStackTrace(); 99 if (stackTrace && stackTrace.length > 0) { 100 result += "\n" + stringifyStackTrace(throwable.getStackTrace()); 101 } 102 var cause = throwable.getCause(); 103 if (cause) { 104 result += "\nCaused by: " + cause; 105 } 106 return result; 107 } 108 109 /** 110 * Stringifies the passed-in {@code stackTrace} array that contains 111 * {@link StackTraceElement} instances. 112 * 113 * <p>The individual {@code StackTraceElement} instances are responsible for 114 * stringifying themselves. 115 * 116 * <p>The resulting string representation is composed as follows: 117 * <pre> 118 * at theStringRepresentationOfTheFirstStackTraceElement 119 * at theStringRepresentationOfTheSecondStackTraceElement 120 * .. 121 * </pre> 122 * 123 * <p>A real string representation could look like this: 124 * <pre> 125 * at org.as2lib.data.math.Range.setNumber(Number) 126 * at org.as2lib.data.holder.MyDataHolder.setMaximumLength(Number) 127 * at com.simonwacker.MyApplication.initialize() 128 * </pre> 129 * 130 * @param stackTrace the stack trace to stringify 131 * @return the string representation of the passed-in {@code stackTrace} 132 */ 133 public function stringifyStackTrace(stackTrace:Array):String { 134 var result:String = ""; 135 for (var i:Number = 0; i < stackTrace.length; i++) { 136 var element:StackTraceElement = stackTrace[i]; 137 result += (" at " 138 + element.toString()); 139 if (i < stackTrace.length-1) { 140 result += "\n"; 141 } 142 } 143 return result; 144 } 145 146 }