forward port r1543135 with
 svn merge -c1543135 ^/tiles/framework/branches/TILES_3_0_X .

>     TILES-574 Tiles expressions do not work after wildcard


git-svn-id: https://svn.apache.org/repos/asf/tiles/framework/trunk@1543136 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tiles-core/src/main/java/org/apache/tiles/definition/pattern/PatternUtil.java b/tiles-core/src/main/java/org/apache/tiles/definition/pattern/PatternUtil.java
index 569416e..edc82b9 100644
--- a/tiles-core/src/main/java/org/apache/tiles/definition/pattern/PatternUtil.java
+++ b/tiles-core/src/main/java/org/apache/tiles/definition/pattern/PatternUtil.java
@@ -22,6 +22,7 @@
 package org.apache.tiles.definition.pattern;
 
 import java.text.MessageFormat;
+import java.util.ArrayList;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Locale;
@@ -209,16 +210,21 @@
      */
     private static String replace(String st, Object... vars) {
         if (st != null && st.indexOf('{') >= 0) {
-            // remember the invalid "{...}" occurrences
-            Matcher m = INVALID_FORMAT_ELEMENT.matcher(st);
+
             // replace them with markers
-            st = INVALID_FORMAT_ELEMENT.matcher(st).replaceAll("INVALID_FORMAT_ELEMENT");
+            List<String> originals = new ArrayList<String>();
+            for(Matcher m = INVALID_FORMAT_ELEMENT.matcher(st); m.find() ; m = INVALID_FORMAT_ELEMENT.matcher(st)) {
+                originals.add(m.group());
+                st = m.replaceFirst("INVALID_FORMAT_ELEMENT");
+            }
+
             // do the MessageFormat replacement (escaping quote characters)
             st = new MessageFormat(st.replaceAll("'", "'''"), ROOT_LOCALE)
                     .format(vars, new StringBuffer(), null).toString();
+
             // return the markers to their original invalid occurrences
-            while (m.find()) {
-                st = st.replace("INVALID_FORMAT_ELEMENT", m.group());
+            for (String original : originals) {
+                st = st.replaceFirst("INVALID_FORMAT_ELEMENT", original);
             }
         }
         return st;
diff --git a/tiles-core/src/test/java/org/apache/tiles/definition/pattern/PatternUtilTest.java b/tiles-core/src/test/java/org/apache/tiles/definition/pattern/PatternUtilTest.java
index 66218db..ddbfacf 100644
--- a/tiles-core/src/test/java/org/apache/tiles/definition/pattern/PatternUtilTest.java
+++ b/tiles-core/src/test/java/org/apache/tiles/definition/pattern/PatternUtilTest.java
@@ -185,15 +185,69 @@
      * See TILES-502
      */
     @Test
-    public void testReplacePlaceholdersEL() {
+    public void testReplacePlaceholdersEL_0() {
         Map<String, Attribute> attributes = new HashMap<String, Attribute>();
-        attributes.put("something", new Attribute("some-{1}-${requestScope.someVariable}.jsp"));
-        Definition definition = new Definition("definitionName", new Attribute(
-                "template"), attributes);
-        Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef",
-                "value0", "value1", "value2", "value3");
+        Attribute attribute = new Attribute("some-{1}-${requestScope.someVariable}.jsp");
+        attribute.setExpressionObject(new Expression((String)attribute.getValue()));
+        attributes.put("something", attribute);
+        Definition definition = new Definition("definitionName", new Attribute("template"), attributes);
+        Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3");
         assertEquals("nudef", nudef.getName());
-        Attribute attribute = nudef.getAttribute("something");
-        assertEquals("some-value1-${requestScope.someVariable}.jsp", attribute.getValue());
+
+        assertEquals(
+                "some-value1-${requestScope.someVariable}.jsp",
+                nudef.getAttribute("something").getValue());
+
+        assertEquals(
+                "some-value1-${requestScope.someVariable}.jsp",
+                nudef.getAttribute("something").getExpressionObject().getExpression());
+    }
+
+    /**
+     * Test method for
+     * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}.
+     * See TILES-574
+     */
+    @Test
+    public void testReplacePlaceholdersEL_1() {
+        Map<String, Attribute> attributes = new HashMap<String, Attribute>();
+        Attribute attribute = new Attribute("some-{1}-${requestScope.someVariable}-other-{2}.jsp");
+        attribute.setExpressionObject(new Expression((String)attribute.getValue()));
+        attributes.put("something", attribute);
+        Definition definition = new Definition("definitionName", new Attribute("template"), attributes);
+        Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3");
+        assertEquals("nudef", nudef.getName());
+
+        assertEquals(
+                "some-value1-${requestScope.someVariable}-other-value2.jsp",
+                nudef.getAttribute("something").getValue());
+
+        assertEquals(
+                "some-value1-${requestScope.someVariable}-other-value2.jsp",
+                nudef.getAttribute("something").getExpressionObject().getExpression());
+    }
+
+    /**
+     * Test method for
+     * {@link PatternUtil#replacePlaceholders(Definition, String, Object[])}.
+     * See TILES-574
+     */
+    @Test
+    public void testReplacePlaceholdersEL_2() {
+        Map<String, Attribute> attributes = new HashMap<String, Attribute>();
+        Attribute attribute = new Attribute("some-${requestScope.someVariable}-other-{1}-${requestScope.someOtherVariable}.jsp");
+        attribute.setExpressionObject(new Expression((String)attribute.getValue()));
+        attributes.put("something", attribute);
+        Definition definition = new Definition("definitionName", new Attribute("template"), attributes);
+        Definition nudef = PatternUtil.replacePlaceholders(definition, "nudef", "value0", "value1", "value2", "value3");
+        assertEquals("nudef", nudef.getName());
+
+        assertEquals(
+                "some-${requestScope.someVariable}-other-value1-${requestScope.someOtherVariable}.jsp",
+                nudef.getAttribute("something").getValue());
+
+        assertEquals(
+                "some-${requestScope.someVariable}-other-value1-${requestScope.someOtherVariable}.jsp",
+                nudef.getAttribute("something").getExpressionObject().getExpression());
     }
 }