### Eclipse Workspace Patch 1.0
#P xwiki-core-macro-box
Index: src/test/java/org/xwiki/rendering/RenderingTests.java
===================================================================
--- src/test/java/org/xwiki/rendering/RenderingTests.java	(revision 15055)
+++ src/test/java/org/xwiki/rendering/RenderingTests.java	(working copy)
@@ -41,6 +41,7 @@
         suite.addTestsFromResource("macrobox2", true);
         suite.addTestsFromResource("macrobox3", true);
         suite.addTestsFromResource("macrobox4", true);
+        suite.addTestsFromResource("macrobox5", true);
 
         return new RenderingPlexusTestSetup(suite);
     }
Index: src/main/java/org/xwiki/rendering/internal/macro/box/DefaultBoxMacro.java
===================================================================
--- src/main/java/org/xwiki/rendering/internal/macro/box/DefaultBoxMacro.java	(revision 15055)
+++ src/main/java/org/xwiki/rendering/internal/macro/box/DefaultBoxMacro.java	(working copy)
@@ -22,7 +22,6 @@
 import java.io.StringReader;
 import java.util.List;
 
-import org.xwiki.component.manager.ComponentLookupException;
 import org.xwiki.rendering.block.Block;
 import org.xwiki.rendering.macro.MacroExecutionException;
 import org.xwiki.rendering.macro.box.AbstractBoxMacro;
@@ -46,7 +45,7 @@
      * The description of the macro.
      */
     private static final String DESCRIPTION = "Draw a box around provided content.";
-
+    
     /**
      * Create and initialize the descriptor of the macro.
      */
@@ -69,22 +68,6 @@
     }
 
     /**
-     * Get the parser of the current wiki syntax.
-     * 
-     * @param context the context of the macro transformation.
-     * @return the parser of the current wiki syntax.
-     * @throws MacroExecutionException Failed to find source parser.
-     */
-    protected Parser getSyntaxParser(MacroTransformationContext context) throws MacroExecutionException
-    {
-        try {
-            return (Parser) getComponentManager().lookup(Parser.ROLE, context.getSyntax().toIdString());
-        } catch (ComponentLookupException e) {
-            throw new MacroExecutionException("Failed to find source parser", e);
-        }
-    }
-
-    /**
      * Parse provided content with the parser of the current wiki syntax.
      * 
      * @param content the content to parse.
Index: pom.xml
===================================================================
--- pom.xml	(revision 15055)
+++ pom.xml	(working copy)
@@ -50,4 +50,11 @@
       </plugin>
     </plugins>
   </build>
+  <dependencies>
+    <dependency>
+      <groupId>org.xwiki.platform</groupId>
+      <artifactId>xwiki-core-bridge</artifactId>
+      <version>${pom.version}</version>
+    </dependency>
+  </dependencies>
 </project>
Index: src/main/java/org/xwiki/rendering/macro/box/AbstractBoxMacro.java
===================================================================
--- src/main/java/org/xwiki/rendering/macro/box/AbstractBoxMacro.java	(revision 15055)
+++ src/main/java/org/xwiki/rendering/macro/box/AbstractBoxMacro.java	(working copy)
@@ -19,20 +19,30 @@
  */
 package org.xwiki.rendering.macro.box;
 
+import java.io.StringReader;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.regex.Pattern;
 
+import org.apache.commons.lang.StringUtils;
+import org.xwiki.component.manager.ComponentLookupException;
 import org.xwiki.component.manager.ComponentManager;
 import org.xwiki.component.phase.Composable;
 import org.xwiki.rendering.block.Block;
 import org.xwiki.rendering.block.FormatBlock;
+import org.xwiki.rendering.block.ImageBlock;
+import org.xwiki.rendering.block.NewLineBlock;
 import org.xwiki.rendering.block.XMLBlock;
 import org.xwiki.rendering.listener.Format;
+import org.xwiki.rendering.listener.Image;
+import org.xwiki.rendering.listener.URLImage;
 import org.xwiki.rendering.listener.xml.XMLElement;
 import org.xwiki.rendering.macro.AbstractMacro;
 import org.xwiki.rendering.macro.MacroExecutionException;
 import org.xwiki.rendering.macro.descriptor.MacroDescriptor;
+import org.xwiki.rendering.parser.ParseException;
+import org.xwiki.rendering.parser.Parser;
 import org.xwiki.rendering.transformation.MacroTransformationContext;
 
 /**
@@ -110,30 +120,76 @@
     public List<Block> execute(P parameters, String content, MacroTransformationContext context)
         throws MacroExecutionException
     {
-        Map<String, String> classParameter = Collections.singletonMap("class", getClassProperty());
+        String imageParameter = parameters.getImage();
+        String titleParameter = parameters.getTitle();
+        
+        String classParameter = parameters.getCssClass();
+        String cssClass = StringUtils.isEmpty(classParameter)
+            ? getClassProperty()
+            : getClassProperty() + " " + classParameter;
+        Map<String, String> classParameterMap = Collections.singletonMap("class", cssClass);
 
         Block boxBlock;
         if (context.isInlined()) {
-            List<Block> result = parseContent(parameters, content, context);
-            FormatBlock spanBlock = new FormatBlock(result, Format.NONE);
-            spanBlock.setParameters(classParameter);
-
+            List<Block> contentBlocks = parseContent(parameters, content, context);
+            FormatBlock spanBlock = new FormatBlock(contentBlocks, Format.NONE);
+            spanBlock.setParameters(classParameterMap);
             boxBlock = spanBlock;
         } else {
+            boxBlock = new XMLBlock(new XMLElement("div", classParameterMap));
+            
+            //we add the image, if there is one
+            if (!StringUtils.isEmpty(imageParameter)) {
+                Image image = new URLImage(imageParameter);
+                Block imageBlock = new ImageBlock(image, true);
+                boxBlock.addChild(imageBlock);
+                boxBlock.addChild(NewLineBlock.NEW_LINE_BLOCK);
+            }
+            //we add the title, if there is one
+            if (!StringUtils.isEmpty(titleParameter)) {
+                Parser parser = getSyntaxParser(context);
+                List<Block> titleBlocks = parseTitle(parser, titleParameter);
+                boxBlock.addChildren(titleBlocks);
+            }
             // We remove the first leading and trailing new line in non inline mode to have a better readability
             // {{box}}
             // some content
             // {{box}}
             // is the same than
             // {{box}}some content{{box}}
-            List<Block> result = parseContent(parameters, stripSingleNewLine(content), context);
-            boxBlock = new XMLBlock(result, new XMLElement("div", classParameter));
+            List<Block> contentBlocks = parseContent(parameters, stripSingleNewLine(content), context);
+            boxBlock.addChildren(contentBlocks);
         }
 
         return Collections.singletonList(boxBlock);
     }
 
     /**
+     * Renders the box's title.
+     * @param parser the appropriate syntax parser
+     * @param titleParameter the title which is going to be parsed
+     * @return the parsing result
+     * @throws MacroExecutionException if the parsing fails
+     */
+    private static List<Block> parseTitle(Parser parser, String titleParameter) throws MacroExecutionException {
+        try {
+            List<Block> titleBlocks = parser.parse(new StringReader(titleParameter)).getChildren();
+
+            //we try to simplify a bit the generated XDOM tree
+            if (titleBlocks.size() == 1) {
+                List<Block> children = titleBlocks.get(0).getChildren();
+                if (children.size() > 0) {
+                    titleBlocks = children;
+                }
+            }
+            
+            return titleBlocks;
+        } catch (ParseException e) {
+            throw new MacroExecutionException(e.getMessage(), e);
+        }
+    }
+    
+    /**
      * Remove the first and last new line of provided content.
      * 
      * @param content the content to trim.
@@ -147,7 +203,7 @@
             if (content.charAt(0) == NEWLINE_N) {
                 beginIndex = 1;
             } else if (content.startsWith(NEWLINE_RN)) {
-                endIndex = 2;
+                beginIndex = 2;
             } else if (content.charAt(0) == NEWLINE_R) {
                 beginIndex = 1;
             }
@@ -181,10 +237,36 @@
         throws MacroExecutionException;
 
     /**
-     * @return the name of the box class to use when on renderer.
+     * Get the parser of the current wiki syntax.
+     * 
+     * @param context the context of the macro transformation.
+     * @return the parser of the current wiki syntax.
+     * @throws MacroExecutionException Failed to find source parser.
      */
+    protected Parser getSyntaxParser(MacroTransformationContext context) throws MacroExecutionException
+    {
+        try {
+            return (Parser) getComponentManager().lookup(Parser.ROLE, context.getSyntax().toIdString());
+        } catch (ComponentLookupException e) {
+            throw new MacroExecutionException("Failed to find source parser", e);
+        }
+    }
+
+    
+    /**
+     * @return the name of the CSS class to use when rendering, in case no cssClass parameter is specified.
+     */
     protected String getClassProperty()
     {
         return "box";
     }
+
+    /**
+     * @param string the string to analyze
+     * @return If the string is a valid URL or not
+     */
+    private static boolean isURL(String string) {
+        // TODO: to be removed if it's not required
+        return Pattern.matches("[a-zA-Z]+://[a-zA-Z0-9._-/]+", string);
+    }
 }
Index: src/test/resources/macrobox5.test
===================================================================
--- src/test/resources/macrobox5.test	(revision 0)
+++ src/test/resources/macrobox5.test	(revision 0)
@@ -0,0 +1,12 @@
+.#-----------------------------------------------------
+.input|xwiki/2.0
+.#-----------------------------------------------------
+{{box title="[[XWiki>>http://www.xwiki.org]]" cssClass="myCLASS" image="http://l.yimg.com/i/i/fr/tr/usa4.jpg"}}alabala{{/box}}
+.#-----------------------------------------------------
+.expect|xhtml/1.0
+.#-----------------------------------------------------
+<!--startmacro:box|-|title="[[XWiki>>http://www.xwiki.org]]" cssClass="myCLASS" image="http://l.yimg.com/i/i/fr/tr/usa4.jpg"|-|alabala--><div class="box myCLASS"><!--startimage:http://l.yimg.com/i/i/fr/tr/usa4.jpg--><img src="http://l.yimg.com/i/i/fr/tr/usa4.jpg" class="wikimodel-freestanding" alt="http://l.yimg.com/i/i/fr/tr/usa4.jpg"/><!--stopimage--><br/><!--startwikilink:http://www.xwiki.org--><span class="wikiexternallink"><a href="http://www.xwiki.org">XWiki</a></span><!--stopwikilink--><p>alabala</p></div><!--stopmacro-->
+.#-----------------------------------------------------
+.expect|xwiki/2.0
+.#-----------------------------------------------------
+{{box title="[[XWiki>>http://www.xwiki.org]]" cssClass="myCLASS" image="http://l.yimg.com/i/i/fr/tr/usa4.jpg"}}alabala{{/box}}
\ No newline at end of file
Index: src/main/java/org/xwiki/rendering/macro/box/BoxMacroParameters.java
===================================================================
--- src/main/java/org/xwiki/rendering/macro/box/BoxMacroParameters.java	(revision 15055)
+++ src/main/java/org/xwiki/rendering/macro/box/BoxMacroParameters.java	(working copy)
@@ -19,6 +19,9 @@
  */
 package org.xwiki.rendering.macro.box;
 
+import org.apache.commons.lang.StringUtils;
+import org.xwiki.rendering.macro.descriptor.ParameterDescription;
+
 /**
  * Parameters for macro box.
  * 
@@ -26,5 +29,74 @@
  */
 public class BoxMacroParameters
 {
+    /**
+     * Refer to {@link BoxMacroParameters#getCssClass()}.
+     */
+    private String cssClass = StringUtils.EMPTY;
 
+    /**
+     * Refer to {@link #getTitle()}.
+     */
+    private String title = StringUtils.EMPTY;
+    
+    /**
+     * Refer to {@link #getImage()}.
+     */
+    private String image = StringUtils.EMPTY;
+    
+    /**
+     * @return the title to be displayed in the message box.
+     * Note that it can be specified using Wiki 2.0 syntax.
+     */
+    public String getTitle()
+    {
+        return title;
+    }
+
+    /**
+     * @param title - refer to {@link #getTitle()}
+     */
+    @ParameterDescription("the title which is to be displayed in the message box")
+    public void setTitle(String title)
+    {
+        this.title = title;
+    }
+
+    /**
+     * @return the image to be displayed in the message box.
+     * It can be specified as attachment name or as an absolute URL.
+     */
+    public String getImage()
+    {
+        return image;
+    }
+
+    /**
+     * @param image - refer to {@link #getImage()}
+     */
+    @ParameterDescription("the image which is to be displayed in the message box")
+    public void setImage(String image)
+    {
+        this.image = image;
+    }
+
+    /**
+     * @return an optional CSS sheet to be used when rendering this macro. 
+     * If no sheet is specified, the <code>BoxMacro.getClassProperty()</code> is used
+     * to provide a default one.
+     */
+    public String getCssClass()
+    {
+        return cssClass;
+    }
+
+    /**
+     * @param cssClass - refer to {@link BoxMacroParameters#getCssClass()}
+     */
+    @ParameterDescription("the CSS sheet used for rendering the document")
+    public void setCssClass(String cssClass)
+    {
+        this.cssClass = cssClass;
+    }
+
 }
