Index: slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java =================================================================== --- slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java (revision 952) +++ slf4j-api/src/main/java/org/slf4j/helpers/MessageFormatter.java (working copy) @@ -60,11 +60,11 @@ * return the string "Hi there.". *

* @param messagePattern The message pattern which will be parsed and formatted - * @param argument The argument to be substituted in place of the formatting anchor + * @param arg The argument to be substituted in place of the formatting anchor * @return The formatted message */ public static String format(String messagePattern, Object arg) { - return arrayFormat(messagePattern, new Object[] {arg}); + return throwableAwareArrayFormat(messagePattern, new Object[] {arg}).getMessage(); } /** @@ -82,7 +82,7 @@ * @return The formatted message */ public static String format(String messagePattern, Object arg1, Object arg2) { - return arrayFormat(messagePattern, new Object[] {arg1, arg2}); + return throwableAwareArrayFormat(messagePattern, new Object[] {arg1, arg2}).getMessage(); } /** @@ -93,39 +93,77 @@ * @param messagePattern The message pattern which will be parsed and formatted * @param argArray An array of arguments to be substituted in place of formatting anchors * @return The formatted message + * @deprecated You should use throwableAwareArrayFormat instead. */ public static String arrayFormat(String messagePattern, Object[] argArray) { + return throwableAwareArrayFormat(messagePattern, argArray).getMessage(); + } + + /** + * Same principle as the {@link #format(String, Object)} and + * {@link #format(String, Object, Object)} methods except that + * any number of arguments can be passed in an array. + * + * This method returns a MessageFormatter.Result which contains the formatted message as well as an optional + * Throwable. + * + * If the last argument is a Throwable and is NOT used by the message pattern it is returned + * in MessageFormatter.Result.getThrowable(). If it is used up getThrowable will return null even + * if the last argument was a Throwable! + * + * @param messagePattern The message pattern which will be parsed and formatted + * @param argArray An array of arguments to be substituted in place of formatting anchors + * @return a MessageFormatter.Result containing the formatted message and optionally a Throwable. + */ + public static Result throwableAwareArrayFormat(String messagePattern, Object[] argArray) { + + Throwable throwable =null; + if(argArray != null && argArray[argArray.length-1] instanceof Throwable) { + throwable = (Throwable) argArray[argArray.length-1]; + } + if(messagePattern == null) { - return null; + return new Result(null, throwable); } + + if(argArray == null) { + return new Result(messagePattern); + } + int i = 0; int len = messagePattern.length(); - int j = messagePattern.indexOf(DELIM_START); - - - + int j; + + + StringBuffer sbuf = new StringBuffer(messagePattern.length() + 50); for (int L = 0; L < argArray.length; L++) { - + char escape = 'x'; - + j = messagePattern.indexOf(DELIM_START, i); if (j == -1 || (j+1 == len)) { // no more variables if (i == 0) { // this is a simple string - return messagePattern; + return new Result(messagePattern, throwable); } else { // add the tail string which contains no variables and return the result. sbuf.append(messagePattern.substring(i, messagePattern.length())); - return sbuf.toString(); + Result result; + if(L<=argArray.length-1) { // there are args left, use throwable if available. + result=new Result(sbuf.toString(), throwable); + } else { // all args are already used up + result=new Result(sbuf.toString()); + } + return result; } } else { char delimStop = messagePattern.charAt(j + 1); if (j > 0) { escape = messagePattern.charAt(j - 1); } - + if(escape == '\\') { L--; // DELIM_START was escaped, thus should not be incremented sbuf.append(messagePattern.substring(i, j-1)); @@ -134,7 +172,13 @@ } else if ((delimStop != DELIM_STOP)) { // invalid DELIM_START/DELIM_STOP pair sbuf.append(messagePattern.substring(i, messagePattern.length())); - return sbuf.toString(); + Result result; + if(L