diff --git a/core/src/main/java/org/apache/struts2/components/ListUIBean.java b/core/src/main/java/org/apache/struts2/components/ListUIBean.java
index 6e24e822e..7d835d322 100644
--- a/core/src/main/java/org/apache/struts2/components/ListUIBean.java
+++ b/core/src/main/java/org/apache/struts2/components/ListUIBean.java
@@ -70,7 +70,7 @@ public abstract class ListUIBean extends UIBean {
if (list instanceof String) {
value = findValue((String) list);
- } else if (list instanceof Collection) {
+ } else if (list instanceof Collection || list instanceof Map) {
value = list;
} else if (MakeIterator.isIterable(list)) {
value = MakeIterator.convert(list);
@@ -107,6 +107,8 @@ public abstract class ListUIBean extends UIBean {
addParameter("listKey", listKey);
} else if (value instanceof Map) {
addParameter("listKey", "key");
+ } else {
+ addParameter("listKey", "top");
}
if (listValueKey != null) {
@@ -119,6 +121,8 @@ public abstract class ListUIBean extends UIBean {
addParameter("listValue", listValue);
} else if (value instanceof Map) {
addParameter("listValue", "value");
+ } else {
+ addParameter("listValue", "top");
}
if (listLabelKey != null) {
diff --git a/core/src/main/java/org/apache/struts2/components/OptGroup.java b/core/src/main/java/org/apache/struts2/components/OptGroup.java
index 58d0b9a72..95d94d26e 100644
--- a/core/src/main/java/org/apache/struts2/components/OptGroup.java
+++ b/core/src/main/java/org/apache/struts2/components/OptGroup.java
@@ -127,7 +127,7 @@ public class OptGroup extends Component {
}
@StrutsTagAttribute(description="Set the list attribute.")
- public void setList(String list) {
+ public void setList(Object list) {
internalUiBean.setList(list);
}
diff --git a/core/src/main/resources/template/simple/optgroup.ftl b/core/src/main/resources/template/simple/optgroup.ftl
index f1f8a3e9e..765591cca 100644
--- a/core/src/main/resources/template/simple/optgroup.ftl
+++ b/core/src/main/resources/template/simple/optgroup.ftl
@@ -21,27 +21,26 @@
<#if parameters.optGroupInternalListUiBeanList??>
<#assign optGroupInternalListUiBeans=parameters.optGroupInternalListUiBeanList />
<#list optGroupInternalListUiBeans as optGroupInternalListUiBean>
-
diff --git a/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java b/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java
index 1067ddd16..506bad30f 100644
--- a/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java
+++ b/core/src/test/java/org/apache/struts2/views/freemarker/FreemarkerResultMockedTest.java
@@ -194,6 +194,53 @@ public class FreemarkerResultMockedTest extends StrutsInternalTestCase {
assertEquals(expected, stringWriter.toString());
}
+ public void testSequenceForSelect() throws Exception {
+ File file = new File(FreeMarkerResultTest.class.getResource("select.ftl").toURI());
+ EasyMock.expect(servletContext.getRealPath("/tutorial/org/apache/struts2/views/freemarker/select.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new File(ClassLoaderUtil.getResource("template/simple/select.ftl", getClass()).toURI());
+ EasyMock.expect(servletContext.getRealPath("/template/simple/select.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/~~~simple/select.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new File(ClassLoaderUtil.getResource("template/simple/optgroup.ftl", getClass()).toURI());
+ EasyMock.expect(servletContext.getRealPath("/template/simple/optgroup.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/~~~simple/optgroup.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new File(ClassLoaderUtil.getResource("template/simple/css.ftl", getClass()).toURI());
+ EasyMock.expect(servletContext.getRealPath("/template/simple/css.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/~~~simple/css.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new File(ClassLoaderUtil.getResource("template/simple/scripting-events.ftl", getClass()).toURI());
+ EasyMock.expect(servletContext.getRealPath("/template/simple/scripting-events.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/~~~simple/scripting-events.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new File(ClassLoaderUtil.getResource("template/simple/common-attributes.ftl", getClass()).toURI());
+ EasyMock.expect(servletContext.getRealPath("/template/simple/common-attributes.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/~~~simple/common-attributes.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new File(ClassLoaderUtil.getResource("template/simple/dynamic-attributes.ftl", getClass()).toURI());
+ EasyMock.expect(servletContext.getRealPath("/template/simple/dynamic-attributes.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/~~~simple/dynamic-attributes.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new File(ClassLoaderUtil.getResource("template/simple/empty.ftl", getClass()).toURI());
+ EasyMock.expect(servletContext.getRealPath("/template/simple/empty.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/~~~simple/empty.ftl")).andReturn(file.getAbsolutePath());
+ EasyMock.expect(servletContext.getRealPath("/template/xhtml/empty.ftl")).andReturn(file.getAbsolutePath());
+
+ EasyMock.replay(servletContext);
+
+ init();
+
+ request.setRequestURI("/tutorial/test9.action");
+ ActionMapping mapping = container.getInstance(ActionMapper.class).getMapping(request, configurationManager);
+ dispatcher.serviceAction(request, response, mapping);
+ String result = stringWriter.toString();
+ assertTrue(result.contains(""));
+ assertTrue(result.contains(""));
+ assertTrue(result.contains(""));
+ assertTrue(result.contains(""));
+ }
+
private void init() throws MalformedURLException, URISyntaxException {
stringWriter = new StringWriter();
writer = new PrintWriter(stringWriter);
diff --git a/core/src/test/resources/org/apache/struts2/views/freemarker/select.ftl b/core/src/test/resources/org/apache/struts2/views/freemarker/select.ftl
new file mode 100644
index 000000000..905053917
--- /dev/null
+++ b/core/src/test/resources/org/apache/struts2/views/freemarker/select.ftl
@@ -0,0 +1,26 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<@s.select theme="simple" list=['a','b','c'] />
+<@s.select theme="simple" list={'key':'value'} />
+<@s.select theme="simple">
+<@s.optgroup label="label1" list={'optgroupKey1':'optgroupValue1','optgroupKey2':'optgroupValue2'} />
+<@s.optgroup label="label2" disabled=true list=['optgroupKey3','optgroupKey4'] />
+@s.select>
\ No newline at end of file
diff --git a/core/src/test/resources/struts.xml b/core/src/test/resources/struts.xml
index 5b29c1e87..0b370aa3e 100644
--- a/core/src/test/resources/struts.xml
+++ b/core/src/test/resources/struts.xml
@@ -80,6 +80,12 @@
+
+
+ org/apache/struts2/views/freemarker/select.ftl
+
+
+