You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/12/15 08:07:11 UTC

svn commit: r1422198 - in /logging/log4j/log4j2/trunk: api/src/main/java/org/apache/logging/log4j/message/ api/src/test/java/org/apache/logging/log4j/message/ api/src/test/resources/ core/src/main/java/org/apache/logging/log4j/core/selector/ jcl-bridge...

Author: rgoers
Date: Sat Dec 15 07:07:07 2012
New Revision: 1422198

URL: http://svn.apache.org/viewvc?rev=1422198&view=rev
Log:
Add MessageFormatMessage and FormattedMessage.

Added:
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java
      - copied, changed from r1418761, logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java
      - copied, changed from r1416796, logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessageFactory.java
      - copied, changed from r1418604, logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java
    logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/FormattedMessageTest.java
    logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/LocalizedMessageTest.java
    logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatMessageTest.java
      - copied, changed from r1418761, logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java
    logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatsPerfTest.java
    logging/log4j/log4j2/trunk/api/src/test/resources/MF_en_US.properties
    logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr.properties
    logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr_CH.properties
    logging/log4j/log4j2/trunk/api/src/test/resources/SF_en_US.properties
    logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr.properties
    logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr_CH.properties
Modified:
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java
    logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java
    logging/log4j/log4j2/trunk/jcl-bridge/pom.xml
    logging/log4j/log4j2/trunk/jcl-bridge/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java
    logging/log4j/log4j2/trunk/jcl-bridge/src/site/xdoc/index.xml
    logging/log4j/log4j2/trunk/log4j12-api/src/site/xdoc/index.xml
    logging/log4j/log4j2/trunk/samples/pom.xml
    logging/log4j/log4j2/trunk/slf4j-impl/pom.xml
    logging/log4j/log4j2/trunk/slf4j-impl/src/site/xdoc/index.xml
    logging/log4j/log4j2/trunk/src/changes/changes.xml
    logging/log4j/log4j2/trunk/src/site/site.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/messages.xml

Copied: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java (from r1418761, logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java?p2=logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java&p1=logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java&r1=1418761&r2=1422198&rev=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java (original)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessage.java Sat Dec 15 07:07:07 2012
@@ -23,13 +23,17 @@ import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.text.Format;
+import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.IllegalFormatException;
+import java.util.regex.Pattern;
 
 /**
- * Handles messages that consist of a format string conforming to java.util.Formatter.
+ * Handles messages that contain a format String. Dynamically determines if the format conforms to
+ * MessageFormat or String.format and if not then uses ParameterizedMessage to format.
  */
-public class StringFormattedMessage implements Message, Serializable {
+public class FormattedMessage implements Message, Serializable {
 
     private static final Logger LOGGER = StatusLogger.getLogger();
 
@@ -41,19 +45,60 @@ public class StringFormattedMessage impl
     private transient Object[] argArray;
     private String[] stringArgs;
     private transient String formattedMessage;
+    private Throwable throwable;
 
-    public StringFormattedMessage(String messagePattern, Object... arguments) {
+    private Message message;
+
+    private static final String formatSpecifier
+        = "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
+
+    private static final Pattern MSG_PATTERN = Pattern.compile(formatSpecifier);
+
+
+    public FormattedMessage(String messagePattern, Object[] arguments, Throwable throwable) {
         this.messagePattern = messagePattern;
         this.argArray = arguments;
+        this.throwable = throwable;
+    }
+
+    public FormattedMessage(String messagePattern, Object[] arguments) {
+        this.messagePattern = messagePattern;
+        this.argArray = arguments;
+        this.throwable = null;
+    }
+
+    /**
+     * Constructor with a pattern and a single parameter.
+     * @param messagePattern The message pattern.
+     * @param arg The parameter.
+     */
+    public FormattedMessage(String messagePattern, Object arg) {
+        this.messagePattern = messagePattern;
+        this.argArray = new Object[] {arg};
+        this.throwable = null;
     }
 
     /**
+     * Constructor with a pattern and two parameters.
+     * @param messagePattern The message pattern.
+     * @param arg1 The first parameter.
+     * @param arg2 The second parameter.
+     */
+    public FormattedMessage(String messagePattern, Object arg1, Object arg2) {
+        this(messagePattern, new Object[]{arg1, arg2});
+    }
+
+
+    /**
      * Returns the formatted message.
      * @return the formatted message.
      */
     public String getFormattedMessage() {
         if (formattedMessage == null) {
-            formattedMessage = formatMessage(messagePattern, argArray);
+            if (message == null) {
+                message = getMessage(messagePattern, argArray, throwable);
+            }
+            formattedMessage = message.getFormattedMessage();
         }
         return formattedMessage;
     }
@@ -77,13 +122,24 @@ public class StringFormattedMessage impl
         return stringArgs;
     }
 
-    protected String formatMessage(String msgPattern, Object... args) {
+    protected Message getMessage(String msgPattern, Object[] args, Throwable throwable) {
+        try {
+            MessageFormat format = new MessageFormat(msgPattern);
+            Format[] formats = format.getFormats();
+            if (formats != null && formats.length > 0) {
+                return new MessageFormatMessage(msgPattern, args);
+            }
+        } catch (Exception ex) {
+            // Obviously, the message is not a proper pattern for MessageFormat.
+        }
         try {
-            return String.format(msgPattern, args);
-        } catch (IllegalFormatException ife) {
-            LOGGER.error("Unable to format msg: " + msgPattern, ife);
-            return msgPattern;
+            if (MSG_PATTERN.matcher(msgPattern).find()) {
+                return new StringFormattedMessage(msgPattern, args);
+            }
+        } catch (Exception ex) {
+            // Also not properly formatted.
         }
+        return new ParameterizedMessage(msgPattern, args, throwable);
     }
 
     @Override
@@ -95,7 +151,7 @@ public class StringFormattedMessage impl
             return false;
         }
 
-        StringFormattedMessage that = (StringFormattedMessage) o;
+        FormattedMessage that = (FormattedMessage) o;
 
         if (messagePattern != null ? !messagePattern.equals(that.messagePattern) : that.messagePattern != null) {
             return false;
@@ -117,7 +173,7 @@ public class StringFormattedMessage impl
 
     @Override
     public String toString() {
-        return "StringFormatMessage[messagePattern=" + messagePattern + ", args=" +
+        return "FormattedMessage[messagePattern=" + messagePattern + ", args=" +
             Arrays.toString(argArray) +  "]";
     }
 
@@ -148,10 +204,16 @@ public class StringFormattedMessage impl
 
     /**
      * Always returns null.
-     * 
+     *
      * @return null
      */
     public Throwable getThrowable() {
-        return null;
+        if (throwable != null) {
+            return throwable;
+        }
+        if (message == null) {
+            message = getMessage(messagePattern, argArray, throwable);
+        }
+        return message.getThrowable();
     }
 }

Added: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java (added)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/FormattedMessageFactory.java Sat Dec 15 07:07:07 2012
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.message;
+
+/**
+ * Creates {@link FormattedMessage} instances for
+ * {@link #newMessage(String, Object...)}.
+ *
+ * @version $Id:  $
+ */
+public class FormattedMessageFactory extends AbstractMessageFactory {
+
+    /**
+     * Creates {@link StringFormattedMessage} instances.
+     *
+     * @see MessageFactory#newMessage(String, Object...)
+     */
+    public Message newMessage(String message, Object... params) {
+        return new FormattedMessage(message, params);
+    }
+}

Modified: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java (original)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessage.java Sat Dec 15 07:07:07 2012
@@ -20,6 +20,8 @@ import org.apache.logging.log4j.status.S
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
@@ -33,7 +35,7 @@ import java.util.ResourceBundle;
  * used to read the events and display them to the user should also localize and format the
  * messages for the end user.
  */
-public class LocalizedMessage extends ParameterizedMessage implements LoggerNameAwareMessage
+public class LocalizedMessage implements Message, Serializable, LoggerNameAwareMessage
 {
     private static final long serialVersionUID = 3893703791567290742L;
 
@@ -46,145 +48,94 @@ public class LocalizedMessage extends Pa
     private transient StatusLogger logger = StatusLogger.getLogger();
 
     private String loggerName;
-
-    public LocalizedMessage(final String messagePattern, final String[] stringArgs, final Throwable throwable) {
-        super(messagePattern, stringArgs, throwable);
-        setup(null, null, null);
-    }
-
-
-    public LocalizedMessage(final String bundleId, final String key, final String[] stringArgs,
-                            final Throwable throwable) {
-        super(key, stringArgs, throwable);
-        setup(bundleId, null, null);
-    }
-
-    public LocalizedMessage(final ResourceBundle bundle, final String key, final String[] stringArgs,
-                            final Throwable throwable) {
-        super(key, stringArgs, throwable);
-        setup(null, bundle, null);
-    }
-
-    public LocalizedMessage(final String bundleId, final Locale locale, final String key, final String[] stringArgs,
-                            final Throwable throwable) {
-        super(key, stringArgs, throwable);
-        setup(bundleId, null, locale);
-    }
-
-    public LocalizedMessage(final ResourceBundle bundle, final Locale locale, final String key, final String[] stringArgs,
-                            final Throwable throwable) {
-        super(key, stringArgs, throwable);
-        setup(null, bundle, locale);
-    }
-
-    public LocalizedMessage(final Locale locale, final String key, final String[] stringArgs, final Throwable throwable) {
-        super(key, stringArgs, throwable);
-        setup(null, null, locale);
-    }
-
+    private String messagePattern;
+    private String[] stringArgs;
+    private transient Object[] argArray;
+    private String formattedMessage;
+    private transient Throwable throwable;
 
     /**
-     * <p>This method returns a LocalizedMessage which contains the arguments converted to String
-     * as well as an optional Throwable.</p>
-     * <p/>
-     * <p>If the last argument is a Throwable and is NOT used up by a placeholder in the message
-     * pattern it is returned in LocalizedMessage.getThrowable() and won't be contained in the
-     * created String[].<br/>
-     * If it is used up ParameterizedMessage.getThrowable() will return null even if the last
-     * argument was a Throwable!</p>
+     * <p></p>
      *
      * @param messagePattern the message pattern that to be checked for placeholders.
      * @param arguments      the argument array to be converted.
      */
     public LocalizedMessage(final String messagePattern, final Object[] arguments) {
-        super(messagePattern, arguments);
-        setup(null, null, null);
+        this((ResourceBundle) null, (Locale) null, messagePattern, arguments);
     }
 
     public LocalizedMessage(final String bundleId, final String key, final Object[] arguments) {
-        super(key, arguments);
-        setup(bundleId, null, null);
+        this(bundleId, (Locale) null, key, arguments);
     }
 
     public LocalizedMessage(final ResourceBundle bundle, final String key, final Object[] arguments) {
-        super(key, arguments);
-        setup(null, bundle, null);
+        this(bundle, (Locale)null, key, arguments);
     }
 
     public LocalizedMessage(final String bundleId, final Locale locale, final String key, final Object[] arguments) {
-        super(key, arguments);
+        this.messagePattern = key;
+        this.argArray = arguments;
+        this.throwable = null;
         setup(bundleId, null, locale);
     }
 
     public LocalizedMessage(final ResourceBundle bundle, final Locale locale, final String key, final Object[] arguments) {
-        super(key, arguments);
+        this.messagePattern = key;
+        this.argArray = arguments;
+        this.throwable = null;
         setup(null, bundle, locale);
     }
 
     public LocalizedMessage(final Locale locale, final String key, final Object[] arguments) {
-        super(key, arguments);
-        setup(null, null, locale);
+        this((ResourceBundle) null, locale, key, arguments);
     }
 
     public LocalizedMessage(final String messagePattern, final Object arg) {
-        super(messagePattern, arg);
-        setup(null, null, null);
+        this((ResourceBundle) null, (Locale) null, messagePattern, new Object[] {arg});
     }
 
     public LocalizedMessage(final String bundleId, final String key, final Object arg) {
-        super(key, arg);
-        setup(bundleId, null, null);
+        this(bundleId, (Locale) null, key, new Object[] {arg});
     }
 
     public LocalizedMessage(final ResourceBundle bundle, final String key, final Object arg) {
-        super(key, arg);
-        setup(null, bundle, null);
+        this(bundle, (Locale) null, key, new Object[] {arg});
     }
 
     public LocalizedMessage(final String bundleId, final Locale locale, final String key, final Object arg) {
-        super(key, arg);
-        setup(bundleId, null, locale);
+        this(bundleId, locale, key, new Object[] {arg});
     }
 
     public LocalizedMessage(final ResourceBundle bundle, final Locale locale, final String key, final Object arg) {
-        super(key, arg);
-        setup(null, bundle, locale);
+        this(bundle, locale, key, new Object[] {arg});
     }
 
     public LocalizedMessage(final Locale locale, final String key, final Object arg) {
-        super(key, arg);
-        setup(null, null, locale);
+        this((ResourceBundle) null, locale, key, new Object[] {arg});
     }
 
     public LocalizedMessage(final String messagePattern, final Object arg1, final Object arg2) {
-        super(messagePattern, arg1, arg2);
-        setup(null, null, null);
+        this((ResourceBundle) null, (Locale) null, messagePattern, new Object[] {arg1, arg2});
     }
 
     public LocalizedMessage(final String bundleId, final String key, final Object arg1, final Object arg2) {
-        super(key, arg1, arg2);
-        setup(bundleId, null, null);
+        this(bundleId, (Locale) null, key, new Object[] {arg1, arg2});
     }
 
     public LocalizedMessage(final ResourceBundle bundle, final String key, final Object arg1, final Object arg2) {
-        super(key, arg1, arg2);
-        setup(null, bundle, null);
+        this(bundle, (Locale) null, key, new Object[] {arg1, arg2});
     }
 
     public LocalizedMessage(final String bundleId, final Locale locale, final String key, final Object arg1, final Object arg2) {
-        super(key, arg1, arg2);
-        setup(bundleId, null, locale);
+        this(bundleId, locale, key, new Object[] {arg1, arg2});
     }
 
-    public LocalizedMessage(final ResourceBundle bundle, final Locale locale, final String key, final Object arg1,
-                            final Object arg2) {
-        super(key, arg1, arg2);
-        setup(null, bundle, locale);
+    public LocalizedMessage(ResourceBundle bundle, Locale locale, String key, Object arg1, Object arg2) {
+        this(bundle, locale, key, new Object[] {arg1, arg2});
     }
 
     public LocalizedMessage(final Locale locale, final String key, final Object arg1, final Object arg2) {
-        super(key, arg1, arg2);
-        setup(null, null, locale);
+        this((ResourceBundle) null, locale, key, new Object[] {arg1, arg2});
     }
 
     /**
@@ -211,12 +162,12 @@ public class LocalizedMessage extends Pa
 
     /**
      * Returns the formatted message after looking up the format in the resource bundle.
-     * @param messagePattern The key for the resource bundle or the pattern if the bundle doesn't contain the key.
-     * @param args The parameters.
      * @return The formatted message String.
      */
-    @Override
-    public String formatMessage(final String messagePattern, final String[] args) {
+    public String getFormattedMessage() {
+        if (formattedMessage != null) {
+            return formattedMessage;
+        }
         ResourceBundle bundle = this.bundle;
         if (bundle == null) {
             if (bundleId != null) {
@@ -225,9 +176,29 @@ public class LocalizedMessage extends Pa
                 bundle = getBundle(loggerName, locale, true);
             }
         }
-        final String msgPattern = (bundle == null || !bundle.containsKey(messagePattern)) ?
+        String messagePattern = getFormat();
+        String msgPattern = (bundle == null || !bundle.containsKey(messagePattern)) ?
             messagePattern : bundle.getString(messagePattern);
-        return format(msgPattern, args);
+        Object[] array = argArray == null ? stringArgs : argArray;
+        FormattedMessage msg = new FormattedMessage(msgPattern, array);
+        formattedMessage = msg.getFormattedMessage();
+        throwable = msg.getThrowable();
+        return formattedMessage;
+    }
+
+    public String getFormat() {
+        return messagePattern;
+    }
+
+    public Object[] getParameters() {
+        if (argArray != null) {
+            return argArray;
+        }
+        return stringArgs;
+    }
+
+    public Throwable getThrowable() {
+        return throwable;
     }
 
     /**
@@ -274,9 +245,33 @@ public class LocalizedMessage extends Pa
         return rb;
     }
 
-    private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
-        stream.defaultReadObject();
-        bundle = null;
+    private void writeObject(ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        getFormattedMessage();
+        out.writeUTF(formattedMessage);
+        out.writeUTF(messagePattern);
+        out.writeUTF(bundleId);
+        out.writeInt(argArray.length);
+        stringArgs = new String[argArray.length];
+        int i = 0;
+        for (Object obj : argArray) {
+            stringArgs[i] = obj.toString();
+            ++i;
+        }
+    }
+
+    private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        formattedMessage = in.readUTF();
+        messagePattern = in.readUTF();
+        bundleId = in.readUTF();
+        int length = in.readInt();
+        stringArgs = new String[length];
+        for (int i = 0; i < length; ++i) {
+            stringArgs[i] = in.readUTF();
+        }
         logger = StatusLogger.getLogger();
+        bundle = null;
+        argArray = null;
     }
 }

Added: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java (added)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/LocalizedMessageFactory.java Sat Dec 15 07:07:07 2012
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.message;
+
+import java.util.ResourceBundle;
+
+/**
+ * Creates {@link org.apache.logging.log4j.message.LocalizedMessage} instances for
+ * {@link #newMessage(String, Object...)}.
+ *
+ * @version $Id:  $
+ */
+public class LocalizedMessageFactory extends AbstractMessageFactory {
+
+    private final ResourceBundle bundle;
+    private final String bundleId;
+
+    public LocalizedMessageFactory(ResourceBundle bundle) {
+        this.bundle = bundle;
+        this.bundleId = null;
+    }
+
+
+    public LocalizedMessageFactory(String bundleId) {
+        this.bundle = null;
+        this.bundleId = bundleId;
+    }
+
+
+    /**
+     * Creates {@link org.apache.logging.log4j.message.StringFormattedMessage} instances.
+     *
+     * @see org.apache.logging.log4j.message.MessageFactory#newMessage(String, Object...)
+     */
+    public Message newMessage(String message, Object... params) {
+        if (bundle == null) {
+            return new LocalizedMessage(bundleId,  message, params);
+        }
+        return new LocalizedMessage(bundle, message, params);
+    }
+}

Copied: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java (from r1416796, logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java?p2=logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java&p1=logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java&r1=1416796&r2=1422198&rev=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormattedMessage.java (original)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessage.java Sat Dec 15 07:07:07 2012
@@ -23,13 +23,14 @@ import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.IllegalFormatException;
 
 /**
- * Handles messages that consist of a format string conforming to java.util.Formatter.
+ * Handles messages that consist of a format string conforming to java.text.MessageFormat.
  */
-public class StringFormattedMessage implements Message, Serializable {
+public class MessageFormatMessage implements Message, Serializable {
 
     private static final Logger LOGGER = StatusLogger.getLogger();
 
@@ -42,7 +43,7 @@ public class StringFormattedMessage impl
     private String[] stringArgs;
     private transient String formattedMessage;
 
-    public StringFormattedMessage(String messagePattern, Object... arguments) {
+    public MessageFormatMessage(String messagePattern, Object... arguments) {
         this.messagePattern = messagePattern;
         this.argArray = arguments;
     }
@@ -79,7 +80,7 @@ public class StringFormattedMessage impl
 
     protected String formatMessage(String msgPattern, Object... args) {
         try {
-            return String.format(msgPattern, args);
+            return MessageFormat.format(msgPattern, args);
         } catch (IllegalFormatException ife) {
             LOGGER.error("Unable to format msg: " + msgPattern, ife);
             return msgPattern;
@@ -95,7 +96,7 @@ public class StringFormattedMessage impl
             return false;
         }
 
-        StringFormattedMessage that = (StringFormattedMessage) o;
+        MessageFormatMessage that = (MessageFormatMessage) o;
 
         if (messagePattern != null ? !messagePattern.equals(that.messagePattern) : that.messagePattern != null) {
             return false;
@@ -145,4 +146,13 @@ public class StringFormattedMessage impl
             stringArgs[i] = in.readUTF();
         }
     }
+
+    /**
+     * Always returns null.
+     *
+     * @return null
+     */
+    public Throwable getThrowable() {
+        return null;
+    }
 }

Copied: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessageFactory.java (from r1418604, logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessageFactory.java?p2=logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessageFactory.java&p1=logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java&r1=1418604&r2=1422198&rev=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StringFormatterMessageFactory.java (original)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/MessageFormatMessageFactory.java Sat Dec 15 07:07:07 2012
@@ -17,18 +17,19 @@
 package org.apache.logging.log4j.message;
 
 /**
- * Creates {@link StringFormattedMessage} instances for {@link #newMessage(String, Object...)}.
- * 
+ * Creates {@link org.apache.logging.log4j.message.MessageFormatMessage} instances for
+ * {@link #newMessage(String, Object...)}.
+ *
  * @version $Id$
  */
-public class StringFormatterMessageFactory extends AbstractMessageFactory {
+public class MessageFormatMessageFactory extends AbstractMessageFactory {
 
     /**
-     * Creates {@link StringFormattedMessage} instances.
-     * 
-     * @see MessageFactory#newMessage(String, Object...)
+     * Creates {@link org.apache.logging.log4j.message.StringFormattedMessage} instances.
+     *
+     * @see org.apache.logging.log4j.message.MessageFactory#newMessage(String, Object...)
      */
     public Message newMessage(String message, Object... params) {
-        return new StringFormattedMessage(message, params);
+        return new MessageFormatMessage(message, params);
     }
 }

Added: logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/FormattedMessageTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/FormattedMessageTest.java?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/FormattedMessageTest.java (added)
+++ logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/FormattedMessageTest.java Sat Dec 15 07:07:07 2012
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.message;
+
+import org.apache.logging.log4j.Timer;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ */
+public class FormattedMessageTest {
+
+    private static final int LOOP_CNT = 500;
+    String[] array = new String[LOOP_CNT];
+
+    @Test
+    public void testStringNoArgs() {
+        String testMsg = "Test message %1s";
+        FormattedMessage msg = new FormattedMessage(testMsg, (Object[]) null);
+        String result = msg.getFormattedMessage();
+        String expected = "Test message null";
+        assertEquals(expected, result);
+        Object[] array = null;
+        msg = new FormattedMessage(testMsg, array, null);
+        result = msg.getFormattedMessage();
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void tesStringtOneArg() {
+        String testMsg = "Test message %1s";
+        FormattedMessage msg = new FormattedMessage(testMsg, "Apache");
+        String result = msg.getFormattedMessage();
+        String expected = "Test message Apache";
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testNoArgs() {
+        String testMsg = "Test message {0}";
+        FormattedMessage msg = new FormattedMessage(testMsg, (Object[]) null);
+        String result = msg.getFormattedMessage();
+        String expected = "Test message {0}";
+        assertEquals(expected, result);
+        Object[] array = null;
+        msg = new FormattedMessage(testMsg, array, null);
+        result = msg.getFormattedMessage();
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testOneArg() {
+        String testMsg = "Test message {0}";
+        FormattedMessage msg = new FormattedMessage(testMsg, "Apache");
+        String result = msg.getFormattedMessage();
+        String expected = "Test message Apache";
+        assertEquals(expected, result);
+    }
+
+    @Test
+    public void testParamNoArgs() {
+        String testMsg = "Test message {}";
+        FormattedMessage msg = new FormattedMessage(testMsg, null);
+        String result = msg.getFormattedMessage();
+        assertEquals(testMsg, result);
+        Object[] array = null;
+        msg = new FormattedMessage(testMsg, array, null);
+        result = msg.getFormattedMessage();
+        assertEquals(testMsg, result);
+    }
+}

Added: logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/LocalizedMessageTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/LocalizedMessageTest.java?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/LocalizedMessageTest.java (added)
+++ logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/LocalizedMessageTest.java Sat Dec 15 07:07:07 2012
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.message;
+
+import org.junit.Test;
+
+import java.util.Locale;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ *
+ */
+public class LocalizedMessageTest {
+
+    private static final int LOOP_CNT = 500;
+    String[] array = new String[LOOP_CNT];
+
+
+    @Test
+    public void testMessageFormat() {
+        LocalizedMessage msg = new LocalizedMessage("MF", new Locale("en_US"), "msg1", new Object[] {"1", "Test"});
+        String result = msg.getFormattedMessage();
+        String expected = "This is test number 1 with string argument Test.";
+        assertTrue(expected.equals(result));
+    }
+
+
+    @Test
+    public void testStringFormat() {
+        LocalizedMessage msg = new LocalizedMessage("SF", new Locale("en_US"), "msg1", new Object[] {"1", "Test"});
+        String result = msg.getFormattedMessage();
+        String expected = "This is test number 1 with string argument Test.";
+        assertTrue(expected.equals(result));
+    }
+}

Copied: logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatMessageTest.java (from r1418761, logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java)
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatMessageTest.java?p2=logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatMessageTest.java&p1=logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java&r1=1418761&r2=1422198&rev=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java (original)
+++ logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatMessageTest.java Sat Dec 15 07:07:07 2012
@@ -25,73 +25,31 @@ import static org.junit.Assert.assertEqu
 /**
  *
  */
-public class StringFormattedMessageTest {
+public class MessageFormatMessageTest {
 
     private static final int LOOP_CNT = 500;
     String[] array = new String[LOOP_CNT];
-    private static long stringTime = 0;
-    private static long paramTime = 0;
-
-    @AfterClass
-    public static void after() {
-        if (stringTime > paramTime) {
-            System.out.println(String.format("Parameterized is %1$.2f times faster than StringFormat.",
-                ((float) stringTime / paramTime)));
-        } else if (stringTime > paramTime) {
-            System.out.println(String.format("Parameterized is %1$.2f times slower than StringFormat.",
-                ((float) paramTime / stringTime)));
-        } else {
-            System.out.println("The speed of Parameterized and StringFormat are the same");
-        }
-    }
 
     @Test
     public void testNoArgs() {
-        String testMsg = "Test message %1s";
-        StringFormattedMessage msg = new StringFormattedMessage(testMsg, (Object[]) null);
+        String testMsg = "Test message {0}";
+        MessageFormatMessage msg = new MessageFormatMessage(testMsg, (Object[]) null);
         String result = msg.getFormattedMessage();
-        String expected = "Test message null";
+        String expected = "Test message {0}";
         assertEquals(expected, result);
         Object[] array = null;
-        msg = new StringFormattedMessage(testMsg, array, null);
+        msg = new MessageFormatMessage(testMsg, array, null);
         result = msg.getFormattedMessage();
+        expected = "Test message null";
         assertEquals(expected, result);
     }
 
     @Test
     public void testOneArg() {
-        String testMsg = "Test message %1s";
-        StringFormattedMessage msg = new StringFormattedMessage(testMsg, "Apache");
+        String testMsg = "Test message {0}";
+        MessageFormatMessage msg = new MessageFormatMessage(testMsg, "Apache");
         String result = msg.getFormattedMessage();
         String expected = "Test message Apache";
         assertEquals(expected, result);
     }
-
-    @Test
-    public void testStringPerf() {
-        String testMsg = "Test message %1s %2s";
-        Timer timer = new Timer("StringFormat", LOOP_CNT);
-        timer.start();
-        for (int i = 0; i < LOOP_CNT; ++i) {
-            StringFormattedMessage msg = new StringFormattedMessage(testMsg, "Apache", "Log4j");
-            array[i] = msg.getFormattedMessage();
-        }
-        timer.stop();
-        stringTime = timer.getElapsedNanoTime();
-        System.out.println(timer.toString());
-    }
-
-    @Test
-    public void testParameterizedPerf() {
-        String testMsg = "Test message {} {}";
-        Timer timer = new Timer("Parameterized", LOOP_CNT);
-        timer.start();
-        for (int i = 0; i < LOOP_CNT; ++i) {
-            ParameterizedMessage msg = new ParameterizedMessage(testMsg, "Apache", "Log4j");
-            array[i] = msg.getFormattedMessage();
-        }
-        timer.stop();
-        paramTime = timer.getElapsedNanoTime();
-        System.out.println(timer.toString());
-    }
 }

Added: logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatsPerfTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatsPerfTest.java?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatsPerfTest.java (added)
+++ logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/MessageFormatsPerfTest.java Sat Dec 15 07:07:07 2012
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.message;
+
+import org.apache.logging.log4j.Timer;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ */
+public class MessageFormatsPerfTest {
+
+    private static final int LOOP_CNT = 500;
+    String[] array = new String[LOOP_CNT];
+    private static long stringTime = 0;
+    private static long paramTime = 0;
+    private static long msgFormatTime = 0;
+
+    @AfterClass
+    public static void after() {
+        if (stringTime > paramTime) {
+            System.out.println(String.format("Parameterized is %1$.2f times faster than StringFormat.",
+                ((float) stringTime / paramTime)));
+        } else if (stringTime > paramTime) {
+            System.out.println(String.format("Parameterized is %1$.2f times slower than StringFormat.",
+                ((float) paramTime / stringTime)));
+        } else {
+            System.out.println("The speed of Parameterized and StringFormat are the same");
+        }
+        if (msgFormatTime > paramTime) {
+            System.out.println(String.format("Parameterized is %1$.2f times faster than MessageFormat.",
+                ((float) msgFormatTime / paramTime)));
+        } else if (msgFormatTime > paramTime) {
+            System.out.println(String.format("Parameterized is %1$.2f times slower than MessageFormat.",
+                ((float) paramTime / msgFormatTime)));
+        } else {
+            System.out.println("The speed of Parameterized and MessageFormat are the same");
+        }
+    }
+
+    @Test
+    public void testStringPerf() {
+        String testMsg = "Test message %1s %2s";
+        Timer timer = new Timer("StringFormat", LOOP_CNT);
+        timer.start();
+        for (int i = 0; i < LOOP_CNT; ++i) {
+            StringFormattedMessage msg = new StringFormattedMessage(testMsg, "Apache", "Log4j");
+            array[i] = msg.getFormattedMessage();
+        }
+        timer.stop();
+        stringTime = timer.getElapsedNanoTime();
+        System.out.println(timer.toString());
+    }
+
+    @Test
+    public void testMessageFormatPerf() {
+        String testMsg = "Test message {0} {1}";
+        Timer timer = new Timer("MessageFormat", LOOP_CNT);
+        timer.start();
+        for (int i = 0; i < LOOP_CNT; ++i) {
+            MessageFormatMessage msg = new MessageFormatMessage(testMsg, "Apache", "Log4j");
+            array[i] = msg.getFormattedMessage();
+        }
+        timer.stop();
+        msgFormatTime = timer.getElapsedNanoTime();
+        System.out.println(timer.toString());
+    }
+
+    @Test
+    public void testParameterizedPerf() {
+        String testMsg = "Test message {} {}";
+        Timer timer = new Timer("Parameterized", LOOP_CNT);
+        timer.start();
+        for (int i = 0; i < LOOP_CNT; ++i) {
+            ParameterizedMessage msg = new ParameterizedMessage(testMsg, "Apache", "Log4j");
+            array[i] = msg.getFormattedMessage();
+        }
+        timer.stop();
+        paramTime = timer.getElapsedNanoTime();
+        System.out.println(timer.toString());
+    }
+}

Modified: logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java (original)
+++ logging/log4j/log4j2/trunk/api/src/test/java/org/apache/logging/log4j/message/StringFormattedMessageTest.java Sat Dec 15 07:07:07 2012
@@ -29,21 +29,6 @@ public class StringFormattedMessageTest 
 
     private static final int LOOP_CNT = 500;
     String[] array = new String[LOOP_CNT];
-    private static long stringTime = 0;
-    private static long paramTime = 0;
-
-    @AfterClass
-    public static void after() {
-        if (stringTime > paramTime) {
-            System.out.println(String.format("Parameterized is %1$.2f times faster than StringFormat.",
-                ((float) stringTime / paramTime)));
-        } else if (stringTime > paramTime) {
-            System.out.println(String.format("Parameterized is %1$.2f times slower than StringFormat.",
-                ((float) paramTime / stringTime)));
-        } else {
-            System.out.println("The speed of Parameterized and StringFormat are the same");
-        }
-    }
 
     @Test
     public void testNoArgs() {
@@ -66,32 +51,4 @@ public class StringFormattedMessageTest 
         final String expected = "Test message Apache";
         assertEquals(expected, result);
     }
-
-    @Test
-    public void testStringPerf() {
-        final String testMsg = "Test message %1s %2s";
-        final Timer timer = new Timer("StringFormat", LOOP_CNT);
-        timer.start();
-        for (int i = 0; i < LOOP_CNT; ++i) {
-            final StringFormattedMessage msg = new StringFormattedMessage(testMsg, "Apache", "Log4j");
-            array[i] = msg.getFormattedMessage();
-        }
-        timer.stop();
-        stringTime = timer.getElapsedNanoTime();
-        System.out.println(timer.toString());
-    }
-
-    @Test
-    public void testParameterizedPerf() {
-        final String testMsg = "Test message {} {}";
-        final Timer timer = new Timer("Parameterized", LOOP_CNT);
-        timer.start();
-        for (int i = 0; i < LOOP_CNT; ++i) {
-            final ParameterizedMessage msg = new ParameterizedMessage(testMsg, "Apache", "Log4j");
-            array[i] = msg.getFormattedMessage();
-        }
-        timer.stop();
-        paramTime = timer.getElapsedNanoTime();
-        System.out.println(timer.toString());
-    }
 }

Added: logging/log4j/log4j2/trunk/api/src/test/resources/MF_en_US.properties
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/resources/MF_en_US.properties?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/resources/MF_en_US.properties (added)
+++ logging/log4j/log4j2/trunk/api/src/test/resources/MF_en_US.properties Sat Dec 15 07:07:07 2012
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+test=This is the English, US test.
+hello_world=Hello world.
+msg1=This is test number {0} with string argument {1}.

Added: logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr.properties
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr.properties?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr.properties (added)
+++ logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr.properties Sat Dec 15 07:07:07 2012
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+test=Ceci est le test en francais pour la France.
+hello_world=Bonjour la France.
+msg1=Ceci est le test numero {0} contenant l''argument {1}.

Added: logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr_CH.properties
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr_CH.properties?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr_CH.properties (added)
+++ logging/log4j/log4j2/trunk/api/src/test/resources/MF_fr_CH.properties Sat Dec 15 07:07:07 2012
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+test=Ceci est le test en francais pour la p'tite Suisse.
+hello world=Salut le monde.

Added: logging/log4j/log4j2/trunk/api/src/test/resources/SF_en_US.properties
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/resources/SF_en_US.properties?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/resources/SF_en_US.properties (added)
+++ logging/log4j/log4j2/trunk/api/src/test/resources/SF_en_US.properties Sat Dec 15 07:07:07 2012
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+test=This is the English, US test.
+hello_world=Hello world.
+msg1=This is test number %1s with string argument %2s.

Added: logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr.properties
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr.properties?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr.properties (added)
+++ logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr.properties Sat Dec 15 07:07:07 2012
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+test=Ceci est le test en francais pour la France.
+hello_world=Bonjour la France.
+msg1=Ceci est le test numero %1s contenant l''argument %2s.

Added: logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr_CH.properties
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr_CH.properties?rev=1422198&view=auto
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr_CH.properties (added)
+++ logging/log4j/log4j2/trunk/api/src/test/resources/SF_fr_CH.properties Sat Dec 15 07:07:07 2012
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+test=Ceci est le test en francais pour la p'tite Suisse.
+hello world=Salut le monde.

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/selector/ClassLoaderContextSelector.java Sat Dec 15 07:07:07 2012
@@ -100,7 +100,9 @@ public class ClassLoaderContextSelector 
             if (securityManager != null) {
                 final Class clazz = securityManager.getCaller(fqcn);
                 if (clazz != null) {
-                    return locateContext(clazz.getClassLoader(), null);
+                    ClassLoader ldr = clazz.getClassLoader() != null ? clazz.getClassLoader() :
+                        ClassLoader.getSystemClassLoader();
+                    return locateContext(ldr, null);
                 }
             }
 

Modified: logging/log4j/log4j2/trunk/jcl-bridge/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/jcl-bridge/pom.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/jcl-bridge/pom.xml (original)
+++ logging/log4j/log4j2/trunk/jcl-bridge/pom.xml Sat Dec 15 07:07:07 2012
@@ -49,7 +49,12 @@
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>
+      <artifactId>log4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>

Modified: logging/log4j/log4j2/trunk/jcl-bridge/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/jcl-bridge/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/jcl-bridge/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java (original)
+++ logging/log4j/log4j2/trunk/jcl-bridge/src/main/java/org/apache/logging/log4j/jcl/LogFactoryImpl.java Sat Dec 15 07:07:07 2012
@@ -51,7 +51,7 @@ public class LogFactoryImpl extends LogF
             return loggers.get(name);
         }
         throw new LogConfigurationException(
-            "SLF4J Adapter requires base logging system to extend Log4J AbstractLogger");
+            "Commons Logging Adapter requires base logging system to extend Log4J AbstractLogger");
     }
 
     private ConcurrentMap<String, Log> getLoggersMap() {

Modified: logging/log4j/log4j2/trunk/jcl-bridge/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/jcl-bridge/src/site/xdoc/index.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/jcl-bridge/src/site/xdoc/index.xml (original)
+++ logging/log4j/log4j2/trunk/jcl-bridge/src/site/xdoc/index.xml Sat Dec 15 07:07:07 2012
@@ -34,9 +34,16 @@
 
         <section name="Requirements">
            <p>
-             The Commons Logging bridge requires at least Java 5.
+             The Commons Logging Bridge requires at least Java 5 and is dependent on the Log4j 2 API.
           </p>
         </section>
 
+      <section name="Usage">
+        <p>
+          Using the Commons Logging Bridge is straightforward. Simply add the bridge jar along with
+          the other Log4j 2 jars and all logging done using the Commons Logging API will be routed to Log4j.
+        </p>
+      </section>
+
     </body>
 </document>
\ No newline at end of file

Modified: logging/log4j/log4j2/trunk/log4j12-api/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j12-api/src/site/xdoc/index.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j12-api/src/site/xdoc/index.xml (original)
+++ logging/log4j/log4j2/trunk/log4j12-api/src/site/xdoc/index.xml Sat Dec 15 07:07:07 2012
@@ -34,9 +34,18 @@
 
         <section name="Requirements">
            <p>
-             The Log4j 1.2 bridge requires at least Java 5.
+             The Log4j 1.2 bridge requires at least Java 5 and is dependent on the Log4j 2 API and implementation.
           </p>
         </section>
 
+      <section name="Usage">
+        <p>
+          To use the Log4j Legacy Bridge just remove all the Log4j 1.x jars from the application and replace them
+          with the bridge jar. Once in place all logging that uses Log4j 1.x will be routed to Log4j 2. However,
+          applications that attempt to modify legacy Log4j by adding Appenders, Filters, etc may experience problems
+          if they try to verify the success of these actions as these methods are largely no-ops.
+        </p>
+      </section>
+
     </body>
 </document>
\ No newline at end of file

Modified: logging/log4j/log4j2/trunk/samples/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/samples/pom.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/samples/pom.xml (original)
+++ logging/log4j/log4j2/trunk/samples/pom.xml Sat Dec 15 07:07:07 2012
@@ -88,4 +88,17 @@
     <module>flume-remote</module>
     <module>flume-embedded</module>
   </modules>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-site-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <skip>true</skip>
+          <skipDeploy>true</skipDeploy>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
 </project>
\ No newline at end of file

Modified: logging/log4j/log4j2/trunk/slf4j-impl/pom.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/slf4j-impl/pom.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/slf4j-impl/pom.xml (original)
+++ logging/log4j/log4j2/trunk/slf4j-impl/pom.xml Sat Dec 15 07:07:07 2012
@@ -49,6 +49,7 @@
      <dependency>
       <groupId>org.apache.logging.log4j</groupId>
       <artifactId>log4j-core</artifactId>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.logging.log4j</groupId>

Modified: logging/log4j/log4j2/trunk/slf4j-impl/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/slf4j-impl/src/site/xdoc/index.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/slf4j-impl/src/site/xdoc/index.xml (original)
+++ logging/log4j/log4j2/trunk/slf4j-impl/src/site/xdoc/index.xml Sat Dec 15 07:07:07 2012
@@ -34,9 +34,17 @@
 
         <section name="Requirements">
            <p>
-             The SLF4J bridge requires at least Java 5.
+             The SLF4J bridge requires at least Java 5 and has a dependency on the Log4j 2 API.
           </p>
         </section>
 
+      <section name="Usage">
+        <p>
+          The SLF4J bindings provided in this Bridge cause all the SLF4J APIs to be routed to Log4j 2. Simply
+          include the SLF4J Bindings jar along with the Log4j 2 jars to cause all SLF4J logging to be handled
+          by Log4j 2.
+        </p>
+      </section>
+
     </body>
 </document>
\ No newline at end of file

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Sat Dec 15 07:07:07 2012
@@ -23,6 +23,9 @@
 
   <body>
     <release version="2.0-beta4" date="TBD" description="Bug fixes and enhancements">
+      <action dev="rgoers" type="add">
+        Add MessageFormatMessage and FormattedMessage.
+      </action>
       <action issue="LOG4J2-134" dev="ggregory" type="add">
         Use %red, %white, %blue, and so on in the console appender.
       </action>

Modified: logging/log4j/log4j2/trunk/src/site/site.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/site.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/site.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/site.xml Sat Dec 15 07:07:07 2012
@@ -119,9 +119,9 @@
 
     <menu name="Components" inherit="top" img="icon-cog">
       <item name="API" href="log4j-api/index.html"/>
-      <item name="Impl" href="log4j-core/index.html"/>
-      <item name="Log4J 1.2 API" href="log4j-1.2-api/index.html"/>
+      <item name="Implementation" href="log4j-core/index.html"/>
       <item name="Commons Logging Bridge" href="log4j-jcl/index.html"/>
+      <item name="Log4J 1.2 API" href="log4j-1.2-api/index.html"/>
       <item name="SLF4J Binding" href="log4j-slf4j-impl/index.html"/>
       <item name="Apache Flume" href="log4j-flume-ng/index.html"/>
       <item name="Log4j Web" href="log4j-web/index.html"/>

Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/messages.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/messages.xml?rev=1422198&r1=1422197&r2=1422198&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/messages.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/messages.xml Sat Dec 15 07:07:07 2012
@@ -167,11 +167,12 @@ public class MyApp {
       <a name="FormattedMessage"/>
       <h4>FormattedMessage</h4>
         <p>
-          A FormattedMessage will have setFormat and getFormat methods. The setFormat method may be called by a
-          Layout to provide advice on how the Message should be formatted. If the Message doesn't recognize the
-          format name it will simply format the data using its default format. An example of this is the
-          StructuredDataMessage which accepts a format String of "XML" which will cause it to format the event data
-          as XML instead of the RFC 5424 format.
+          The message pattern passed to a
+          <a href="../log4j-api/apidocs/org/apache/logging/log4j/message/FormattedMessage.html">FormattedMessage</a>
+          is first checked to see if it is a valid java.text.MessageFormat pattern. If it is, a MessageFormatMessage is
+          used to format it. If not it is next checked to see if it contains any tokens that are valid format
+          specifiers for String.format(). If so, a StringFormattedMessage is used to format it. Finally, if the
+          pattern doesn't match either of those then a ParameterizedMessage is used to format it.
         </p>
       <a name="LocalizedMessage"/>
       <h4>LocalizedMessage</h4>
@@ -181,10 +182,10 @@ public class MyApp {
           the best approach to localization is to have the client UI render the events in the client's locale.
         </p>
         <p>
-          LocalizedMessage extends a ParameterizedMessage by incorporating a ResourceBundle and allowing
-          the message pattern parameter to be the key to the message pattern in the bundle. If no bundle is specified,
+          LocalizedMessage incorporates a ResourceBundle and allows the message pattern parameter to be the key to
+          the message pattern in the bundle. If no bundle is specified,
           LocalizedMessage will attempt to locate a bundle with the name of the Logger used to log the event. The
-          parameters to the Message will be incorporated into the Message whereever the "{}" placeholders occur.
+          message retrieved from the bundle will be formatted using a FormattedMessage.
         </p>
       <a name="LoggerNameAwareMessage"/>
       <h4>LoggerNameAwareMessage</h4>
@@ -200,6 +201,23 @@ public class MyApp {
           a format specifier of "XML", in which case the Map will be formatted as XML. Otherwise, the Map will be
           formatted as "key1=value1 key2=value2...".
         </p>
+        <a name="MessageFormatMessage"/>
+        <h4>MessageFormatMessage</h4>
+        <p>
+          <a href="../log4j-api/apidocs/org/apache/logging/log4j/message/MessageFormatMessage.html">MessageFormatMessage</a>
+          handles messages that use a <a href="http://docs.oracle.com/javase/6/docs/api/java/text/MessageFormat.html">conversion format</a>.
+          While this Message has more flexibility than ParameterizedMessage, it is also about two times slower.
+        </p>
+      <a name="MultiformatMessage"/>
+      <h4>MultiformatMessage</h4>
+        <p>
+          A MultiformatMessage will have a getFormats method and a getFormattedMessage method that accepts and array
+          of format Strings. The getFormats method may be called by a Layout to provide it information on what
+          formatting optionsthe Message supports. The Layout may then call getFormattedMessage with one or more
+          for the formats. If the Message doesn't recognize the format name it will simply format the data using its
+          default format. An example of this is the StructuredDataMessage which accepts a format String of "XML"
+          which will cause it to format the event data as XML instead of the RFC 5424 format.
+        </p>
       <a name="ObjectMessage"/>
       <h4>ObjectMessage</h4>
         <p>