Author: lukaszlenart
Date: Fri Apr 6 08:17:00 2012
New Revision: 1310221
URL: http://svn.apache.org/viewvc?rev=1310221&view=rev
Log:
WW-3174 adds logic to support dynamic attributes in tags used with FreeMarker
templates
Added:
struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/dynaAttributes.ftl
- copied, changed from r1310204,
struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/UIBean.java
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java
struts/struts2/trunk/core/src/test/resources/struts.xml
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/UIBean.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/UIBean.java?rev=1310221&r1=1310220&r2=1310221&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/UIBean.java
(original)
+++
struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/UIBean.java
Fri Apr 6 08:17:00 2012
@@ -21,31 +21,34 @@
package org.apache.struts2.components;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.inject.Inject;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
import org.apache.struts2.StrutsConstants;
import org.apache.struts2.StrutsException;
-import org.apache.struts2.util.TextProviderHelper;
import org.apache.struts2.components.template.Template;
import org.apache.struts2.components.template.TemplateEngine;
import org.apache.struts2.components.template.TemplateEngineManager;
import org.apache.struts2.components.template.TemplateRenderingContext;
+import org.apache.struts2.util.TextProviderHelper;
import org.apache.struts2.views.annotations.StrutsTagAttribute;
import org.apache.struts2.views.util.ContextUtil;
-import com.opensymphony.xwork2.config.ConfigurationException;
-import com.opensymphony.xwork2.inject.Inject;
-import com.opensymphony.xwork2.util.ValueStack;
-import com.opensymphony.xwork2.util.logging.Logger;
-import com.opensymphony.xwork2.util.logging.LoggerFactory;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
/**
* UIBean is the standard superclass of all Struts UI componentns.
@@ -491,6 +494,9 @@ public abstract class UIBean extends Com
protected String defaultUITheme;
protected TemplateEngineManager templateEngineManager;
+ // dynamic attributes support for tags used with FreeMarker templates
+ protected static Map<Class, Set<String>> standardAttributesMap = new
ConcurrentHashMap<Class, Set<String>>();
+
@Inject(StrutsConstants.STRUTS_UI_TEMPLATEDIR)
public void setDefaultTemplateDir(String dir) {
this.defaultTemplateDir = dir;
@@ -1195,7 +1201,48 @@ public abstract class UIBean extends Com
this.tooltipIconPath = tooltipIconPath;
}
- public void setDynamicAttributes(Map<String,Object> dynamicAttributes) {
- this.dynamicAttributes = dynamicAttributes;
- }
+ public void setDynamicAttributes(Map<String, Object> dynamicAttributes)
{
+ this.dynamicAttributes.putAll(dynamicAttributes);
}
+
+ @Override
+ /**
+ * supports dynamic attributes for freemarker ui tags
+ * @see https://issues.apache.org/jira/browse/WW-3174
+ */
+ public void copyParams(Map params) {
+ super.copyParams(params);
+ Set<String> standardAttributes = getStandardAttributes();
+ for (Object o : params.entrySet()) {
+ Map.Entry entry = (Map.Entry) o;
+ String key = (String) entry.getKey();
+ if (!key.equals("dynamicAttributes") &&
!standardAttributes.contains(key)){
+ dynamicAttributes.put(key, entry.getValue());
+ }
+ }
+ }
+
+ protected Set<String> getStandardAttributes() {
+ Class clz = getClass();
+ Set<String> standardAttributes = standardAttributesMap.get(clz);
+ if (standardAttributes == null) {
+ standardAttributes = new HashSet<String>();
+ standardAttributesMap.put(clz, standardAttributes);
+ while (clz != null) {
+ for (Field f : clz.getDeclaredFields()) {
+ if (Modifier.isProtected(f.getModifiers())
+ && (f.getType().equals(String.class) ||
clz.equals(ListUIBean.class)
+ && f.getName().equals("list")))
+ standardAttributes.add(f.getName());
+ }
+ if (clz.equals(UIBean.class)) {
+ break;
+ } else {
+ clz = clz.getSuperclass();
+ }
+ }
+ }
+ return standardAttributes;
+ }
+
+}
\ No newline at end of file
Modified:
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java?rev=1310221&r1=1310220&r2=1310221&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java
(original)
+++
struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/freemarker/FreeMarkerResultTest.java
Fri Apr 6 08:17:00 2012
@@ -21,12 +21,12 @@
package org.apache.struts2.views.freemarker;
-import java.io.File;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-
-import junit.framework.TestCase;
-
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.mock.MockActionInvocation;
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+import com.opensymphony.xwork2.util.ValueStack;
+import freemarker.template.Configuration;
+import freemarker.template.TemplateExceptionHandler;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.StrutsStatics;
import org.apache.struts2.StrutsTestCase;
@@ -35,20 +35,13 @@ import org.apache.struts2.dispatcher.map
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.views.jsp.StrutsMockHttpServletResponse;
import org.apache.struts2.views.jsp.StrutsMockServletContext;
-import org.springframework.mock.web.MockHttpServletRequest;
-import org.springframework.mock.web.MockServletContext;
-import org.springframework.core.io.DefaultResourceLoader;
import org.easymock.EasyMock;
-
-import com.opensymphony.xwork2.ActionContext;
-import com.opensymphony.xwork2.mock.MockActionInvocation;
-import com.opensymphony.xwork2.util.ValueStack;
-import com.opensymphony.xwork2.util.ValueStackFactory;
+import org.springframework.mock.web.MockHttpServletRequest;
import javax.servlet.ServletContext;
-
-import freemarker.template.TemplateExceptionHandler;
-import freemarker.template.Configuration;
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
/**
* Test case for FreeMarkerResult.
@@ -184,6 +177,46 @@ public class FreeMarkerResultTest extend
assertEquals("text/xml", response.getContentType());
}
+ public void testDynamicAttributesSupport() throws Exception {
+ //get fm config to use it in mock servlet context
+ FreemarkerManager freemarkerManager =
container.getInstance(FreemarkerManager.class);
+ Configuration freemarkerConfig =
freemarkerManager.getConfiguration(ServletActionContext.getServletContext());
+
freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+
+ ServletContext servletContext =
EasyMock.createNiceMock(ServletContext.class);
+
+ File file = new
File(FreeMarkerResultTest.class.getResource("dynaAttributes.ftl").toURI());
+
EasyMock.expect(servletContext.getRealPath("/tutorial/org/apache/struts2/views/freemarker/dynaAttributes.ftl")).andReturn(file.getAbsolutePath());
+
+ file = new
File(ClassLoaderUtil.getResource("template/simple/text.ftl",
getClass()).toURI());
+
EasyMock.expect(servletContext.getRealPath("/template/simple/text.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());
+
+ file = new
File(ClassLoaderUtil.getResource("template/simple/scripting-events.ftl",
getClass()).toURI());
+
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());
+
+ 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.getAttribute(FreemarkerManager.CONFIG_SERVLET_CONTEXT_KEY)).andReturn(freemarkerConfig).anyTimes();
+ EasyMock.replay(servletContext);
+
+ freemarkerConfig.setServletContextForTemplateLoading(servletContext,
null);
+ ServletActionContext.setServletContext(servletContext);
+
+
+ request.setRequestURI("/tutorial/test6.action");
+ Dispatcher dispatcher = Dispatcher.getInstance();
+ ActionMapping mapping =
dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request,
dispatcher.getConfigurationManager());
+ dispatcher.serviceAction(request, response, servletContext, mapping);
+ assertEquals("<input type=\"text\" name=\"test\" value=\"\"
id=\"test\" placeholder=\"input\" foo=\"bar\"/>", stringWriter.toString());
+ }
+
protected void setUp() throws Exception {
super.setUp();
mgr = new FreemarkerManager();
Copied:
struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/dynaAttributes.ftl
(from r1310204,
struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl)
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/dynaAttributes.ftl?p2=struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/dynaAttributes.ftl&p1=struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl&r1=1310204&r2=1310221&rev=1310221&view=diff
==============================================================================
---
struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/callActionFreeMarker.ftl
(original)
+++
struts/struts2/trunk/core/src/test/resources/org/apache/struts2/views/freemarker/dynaAttributes.ftl
Fri Apr 6 08:17:00 2012
@@ -20,4 +20,4 @@
* under the License.
*/
-->
-before<@s.action namespace="/tutorial" name="test4" executeResult="true"
rethrowException="true"/>after
\ No newline at end of file
+<@s.textfield name="test"
dynamicAttributes={"placeholder":"input","foo":"bar"}/>
\ No newline at end of file
Modified: struts/struts2/trunk/core/src/test/resources/struts.xml
URL:
http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/resources/struts.xml?rev=1310221&r1=1310220&r2=1310221&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/test/resources/struts.xml (original)
+++ struts/struts2/trunk/core/src/test/resources/struts.xml Fri Apr 6 08:17:00
2012
@@ -63,6 +63,12 @@
</result>
</action>
+ <action name="test6" class="com.opensymphony.xwork2.ActionSupport">
+ <result type="freemarker">
+ <param
name="location">org/apache/struts2/views/freemarker/dynaAttributes.ftl</param>
+ </result>
+ </action>
+
</package>
<package name="sitegraph" namespace="/tutorial/sitegraph"
extends="struts-default">