Index: xwiki-component/src/main/java/org/xwiki/component/logging/Logger.java
===================================================================
--- xwiki-component/src/main/java/org/xwiki/component/logging/Logger.java	(revision 13673)
+++ xwiki-component/src/main/java/org/xwiki/component/logging/Logger.java	(working copy)
@@ -20,8 +20,11 @@
  */
 package org.xwiki.component.logging;
 
+import java.text.MessageFormat;
+
 public interface Logger
 {
+
     /** Typecode for debugging messages. */
     int LEVEL_DEBUG = 0;
 
@@ -37,28 +40,220 @@
     /** Typecode for disabled log levels. */
     int LEVEL_DISABLED = 5;
 
+    /**
+     * @param message to be logged to debug
+     */
     void debug(String message);
 
+    /**
+     * @param message to be logged to debug
+     * @param throwable Throwable associated with the message for
+     * stacktrace output
+     */
     void debug(String message, Throwable throwable);
 
+    /**
+     * Logs the {@code message} to the logger with debug priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.debug( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     *
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void debug(String message, Object... objects);
+
+    /**
+     * Logs the {@code message} to the logger with debug priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.debug( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     *
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param throwable Throwable associated with the message for stacktrace output
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void debug(String message, Throwable throwable, Object... objects);
+
+    /**
+     * @return {@code true} if messages will be logged to debug
+     */
     boolean isDebugEnabled();
 
+    /**
+     * @param message to be logged to info
+     */
     void info(String message);
 
+    /**
+     * @param message to be logged to info
+     * @param throwable Throwable associated with the message for
+     * stacktrace output
+     */
     void info(String message, Throwable throwable);
 
+    /**
+     * Logs the {@code message} to the logger with info priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.info( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     *
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void info(String message, Object... objects);
+
+    /**
+     * Logs the {@code message} to the logger with info priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.info( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     *
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param throwable Throwable associated with the message for stacktrace output
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void info(String message, Throwable throwable, Object... objects);
+
+    /**
+     * @return {@code true} if messages will be logged to info
+     */
     boolean isInfoEnabled();
 
+    /**
+     * @param message to be logged to warn
+     */
     void warn(String message);
 
+    /**
+     * @param message to be logged to warn
+     * @param throwable Throwable associated with the message for
+     * stacktrace output
+     */
     void warn(String message, Throwable throwable);
 
+    /**
+     * Logs the {@code message} to the logger with warn priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.warn( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     *
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void warn(String message, Object... objects);
+
+    /**
+     * Logs the {@code message} to the logger with warn priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.warn( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     * 
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param throwable Throwable associated with the message for stacktrace output
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void warn(String message, Throwable throwable, Object... objects);
+
+    /**
+     * @return {@code true} if messages will be logged to warn
+     */
     boolean isWarnEnabled();
 
+    /**
+     * @param message to be logged to error
+     */
     void error(String message);
 
+    /**
+     * @param message to be logged to error
+     * @param throwable Throwable associated with the message for
+     * stacktrace output
+     */
     void error(String message, Throwable throwable);
 
+    /**
+     * Logs the {@code message} to the logger with error priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.error( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     *
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void error(String message, Object... objects);
+
+    /**
+     * Logs the {@code message} to the logger with error priority while
+     * expanding the message with the objects passed. The message uses the
+     * {@link java.text.MessageFormat} format String Syntax.
+     * <br>
+     * Example:<br>
+     * <code>
+     * log.error( "Doc was created on {1} and was changed {2} times", date, 5);
+     * </code>
+     * <br>
+     * The logged message will only be assembled if the message is actually logged.
+     * 
+     * @param message The message to be formatted via {@code MessageFormat.format()}
+     * @param throwable Throwable associated with the message for stacktrace output
+     * @param objects The objects to be filled into the message
+     * @see MessageFormat
+     */
+    void error(String message, Throwable throwable, Object... objects);
+
+    /**
+     * @return {@code true} if messages will be logged to error
+     */
     boolean isErrorEnabled();
 
     Logger getChildLogger(String name);
Index: xwiki-plexus/src/main/java/org/xwiki/plexus/logging/PlexusLogger.java
===================================================================
--- xwiki-plexus/src/main/java/org/xwiki/plexus/logging/PlexusLogger.java	(revision 13673)
+++ xwiki-plexus/src/main/java/org/xwiki/plexus/logging/PlexusLogger.java	(working copy)
@@ -20,12 +20,50 @@
  */
 package org.xwiki.plexus.logging;
 
+import java.text.MessageFormat;
 import org.xwiki.component.logging.Logger;
 
 public class PlexusLogger implements Logger
 {
+
     private org.codehaus.plexus.logging.Logger logger;
 
+    /**
+     * Formats the message like {@code MessageFormat.format(String, Object...)} but 
+     * also checks for Exceptions and catches the as logging should be robust
+     * and not interfere with normal program flow. The Exception caught will be
+     * passed to the loggers debug output.
+     * 
+     * @param message message in Formatter format syntax
+     * @param objects Objects to fill in 
+     * @return the formatted String if possible, else the message and all 
+     * objects concatenated.
+     * @see MessageFormat
+     */
+    private String formatMessage(String message, Object... objects)
+    {
+        try {
+            return MessageFormat.format(message, objects);
+        } catch (IllegalArgumentException e) {
+            this.logger.debug("Caught exception while formatting logging message: " + message, e);
+
+            // Try to save the message for logging output and just append the passed objects instead
+            if (objects != null) {
+                StringBuffer sb = new StringBuffer(message);
+                for (Object object : objects) {
+                    if (object != null) {
+                        sb.append(object);
+                    } else {
+                        sb.append("(null)");
+                    }
+                    sb.append(" ");
+                }
+                return sb.toString();
+            }
+            return message;
+        }
+    }
+
     public PlexusLogger(org.codehaus.plexus.logging.Logger logger)
     {
         this.logger = logger;
@@ -41,6 +79,20 @@
         this.logger.debug(message, throwable);
     }
 
+    public void debug(String message, Object... objects)
+    {
+        if (this.logger.isDebugEnabled()) {
+            this.logger.debug(formatMessage(message, objects));
+        }
+    }
+
+    public void debug(String message, Throwable throwable, Object... objects)
+    {
+        if (this.logger.isDebugEnabled()) {
+            this.logger.debug(formatMessage(message, objects), throwable);
+        }
+    }
+
     public boolean isDebugEnabled()
     {
         return this.logger.isDebugEnabled();
@@ -56,6 +108,20 @@
         this.logger.info(message, throwable);
     }
 
+    public void info(String message, Object... objects)
+    {
+        if (this.logger.isInfoEnabled()) {
+            this.logger.info(formatMessage(message, objects));
+        }
+    }
+
+    public void info(String message, Throwable throwable, Object... objects)
+    {
+        if (this.logger.isInfoEnabled()) {
+            this.logger.info(formatMessage(message, objects), throwable);
+        }
+    }
+
     public boolean isInfoEnabled()
     {
         return this.logger.isInfoEnabled();
@@ -71,6 +137,20 @@
         this.logger.warn(message, throwable);
     }
 
+    public void warn(String message, Object... objects)
+    {
+        if (this.logger.isWarnEnabled()) {
+            this.logger.warn(formatMessage(message, objects));
+        }
+    }
+
+    public void warn(String message, Throwable throwable, Object... objects)
+    {
+        if (this.logger.isWarnEnabled()) {
+            this.logger.warn(formatMessage(message, objects), throwable);
+        }
+    }
+
     public boolean isWarnEnabled()
     {
         return this.logger.isWarnEnabled();
@@ -86,6 +166,20 @@
         this.logger.error(message, throwable);
     }
 
+    public void error(String message, Object... objects)
+    {
+        if (this.logger.isErrorEnabled()) {
+            this.logger.error(formatMessage(message, objects));
+        }
+    }
+
+    public void error(String message, Throwable throwable, Object... objects)
+    {
+        if (this.logger.isErrorEnabled()) {
+            this.logger.error(formatMessage(message, objects), throwable);
+        }
+    }
+
     public boolean isErrorEnabled()
     {
         return this.logger.isErrorEnabled();
