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) @@ -49,8 +49,9 @@ * @author Ceki Gülcü */ public class MessageFormatter { - static final char DELIM_START = '{'; - static final char DELIM_STOP = '}'; + private static final char DELIM_START = '{'; + private static final char DELIM_STOP = '}'; + private static final char ESCAPE_CHAR = '\\'; /** * Performs single argument substitution for the 'messagePattern' passed as @@ -60,11 +61,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 +83,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,40 +94,83 @@
* @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';
-
+
+ boolean escaped=false;
+
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 (j > 0 && messagePattern.charAt(j - 1) == ESCAPE_CHAR) {
+ escaped=true;
+ if (j > 1 && messagePattern.charAt(j - 2) == ESCAPE_CHAR) {
+ escaped=false;
+ sbuf.append(messagePattern.substring(i, j-2));
+ i=j-1;
+ }
}
-
- if(escape == '\\') {
+
+ if(escaped) {
L--; // DELIM_START was escaped, thus should not be incremented
sbuf.append(messagePattern.substring(i, j-1));
sbuf.append(DELIM_START);
@@ -134,7 +178,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