/* | |
* 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. | |
*/ | |
package org.apache.struts2.views.jsp; | |
import com.mockobjects.servlet.MockJspWriter; | |
import com.opensymphony.xwork2.ActionContext; | |
import com.opensymphony.xwork2.ActionInvocation; | |
import com.opensymphony.xwork2.ActionProxy; | |
import com.opensymphony.xwork2.util.ValueStack; | |
import com.opensymphony.xwork2.util.ValueStackFactory; | |
import org.apache.struts2.dispatcher.Dispatcher; | |
import org.apache.struts2.dispatcher.mapper.ActionMapping; | |
import org.apache.struts2.portlet.PortletConstants; | |
import org.apache.struts2.portlet.PortletPhase; | |
import org.apache.struts2.portlet.util.PortletUrlHelper; | |
import org.jmock.Mock; | |
import org.jmock.cglib.MockObjectTestCase; | |
import org.jmock.core.Constraint; | |
import org.springframework.mock.web.MockServletContext; | |
import javax.portlet.PortletContext; | |
import javax.portlet.PortletMode; | |
import javax.portlet.PortletURL; | |
import javax.portlet.RenderRequest; | |
import javax.portlet.RenderResponse; | |
import javax.portlet.WindowState; | |
import javax.servlet.ServletContext; | |
import javax.servlet.http.HttpServletRequest; | |
import javax.servlet.http.HttpServletResponse; | |
import javax.servlet.jsp.PageContext; | |
import java.util.Arrays; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
import static org.apache.struts2.StrutsStatics.STRUTS_PORTLET_CONTEXT; | |
/** | |
* | |
*/ | |
@SuppressWarnings("unchecked") | |
public class PortletUrlTagTest extends MockObjectTestCase { | |
URLTag tag = new URLTag(); | |
Mock mockHttpReq = null; | |
Mock mockHttpRes = null; | |
Mock mockPortletReq = null; | |
Mock mockPortletRes = null; | |
Mock mockPageCtx = null; | |
Mock mockPortletUrl = null; | |
MockJspWriter mockJspWriter = null; | |
Mock mockCtx = null; | |
ValueStack stack = null; | |
Mock mockActionProxy = null; | |
Mock mockActionInvocation = null; | |
private Dispatcher dispatcher; | |
public void setUp() throws Exception { | |
super.setUp(); | |
ServletContext servletContext = new MockServletContext(); | |
dispatcher = new Dispatcher(servletContext, new HashMap<>()); | |
dispatcher.init(); | |
Dispatcher.setInstance(dispatcher); | |
stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack(); | |
mockActionInvocation = mock(ActionInvocation.class); | |
mockActionProxy = mock(ActionProxy.class); | |
mockHttpReq = mock(HttpServletRequest.class); | |
mockHttpRes = mock(HttpServletResponse.class); | |
mockPortletReq = mock(RenderRequest.class); | |
mockPortletRes = mock(RenderResponse.class); | |
mockPageCtx = mock(PageContext.class); | |
mockPortletUrl = mock(PortletURL.class); | |
mockJspWriter = new MockJspWriter(); | |
mockCtx = mock(PortletContext.class); | |
mockActionProxy.stubs().method("getNamespace").will(returnValue("/view")); | |
mockActionInvocation.stubs().method("getProxy").will(returnValue( | |
mockActionProxy.proxy())); | |
mockPageCtx.stubs().method("getRequest").will( | |
returnValue(mockHttpReq.proxy())); | |
mockPageCtx.stubs().method("getResponse").will( | |
returnValue(mockHttpRes.proxy())); | |
mockPageCtx.stubs().method("getOut").will(returnValue(mockJspWriter)); | |
mockHttpReq.stubs().method("getScheme").will(returnValue("http")); | |
mockHttpReq.stubs().method("getAttribute").with( | |
eq("struts.valueStack")).will(returnValue(stack)); | |
mockHttpReq.stubs().method("getAttribute").with( | |
eq("javax.portlet.response")).will( | |
returnValue(mockPortletRes.proxy())); | |
mockHttpReq.stubs().method("getAttribute").with( | |
eq("javax.portlet.request")).will( | |
returnValue(mockPortletReq.proxy())); | |
mockHttpReq.stubs().method("getAttribute").with( | |
eq("javax.servlet.include.servlet_path")).will( | |
returnValue("/servletPath")); | |
mockHttpReq.stubs().method("getParameterMap").will( | |
returnValue(Collections.emptyMap())); | |
mockPortletReq.stubs().method("getPortletMode").will(returnValue(PortletMode.VIEW)); | |
mockPortletReq.stubs().method("getWindowState").will(returnValue(WindowState.NORMAL)); | |
mockPortletReq.stubs().method("getContextPath").will(returnValue("/contextPath")); | |
tag.setPageContext((PageContext) mockPageCtx.proxy()); | |
Map<PortletMode, String> modeMap = new HashMap<>(); | |
modeMap.put(PortletMode.VIEW, "/view"); | |
modeMap.put(PortletMode.HELP, "/help"); | |
modeMap.put(PortletMode.EDIT, "/edit"); | |
Map<PortletMode, ActionMapping> actionMap = new HashMap<>(); | |
actionMap.put(PortletMode.VIEW, new ActionMapping("defaultView", "/view", "execute", new HashMap<>())); | |
actionMap.put(PortletMode.HELP, new ActionMapping("defaultHelp", "/help", "execute", new HashMap<>())); | |
actionMap.put(PortletMode.EDIT, new ActionMapping("defaultEdit", "/edit", "execute", new HashMap<>())); | |
Map<String, Object> contextMap = stack.getActionContext() | |
.withSession(new HashMap<>()) | |
.with(PortletConstants.REQUEST, mockPortletReq.proxy()) | |
.with(PortletConstants.RESPONSE, mockPortletRes.proxy()) | |
.with(PortletConstants.PHASE, PortletPhase.RENDER_PHASE) | |
.with(PortletConstants.MODE_NAMESPACE_MAP, modeMap) | |
.with(PortletConstants.DEFAULT_ACTION_MAP, actionMap) | |
.with(STRUTS_PORTLET_CONTEXT, mockCtx.proxy()) | |
.getContextMap(); | |
ActionInvocation ai = (ActionInvocation) mockActionInvocation.proxy(); | |
ActionContext.of(contextMap) | |
.withValueStack(stack) | |
.withContainer(dispatcher.getContainer()) | |
.withActionInvocation(ai) | |
.bind(); | |
} | |
public void tearDown() throws Exception { | |
super.tearDown(); | |
if (dispatcher != null && dispatcher.getConfigurationManager() != null) { | |
dispatcher.cleanup(); | |
dispatcher = null; | |
} | |
} | |
public void testEnsureParamsAreStringArrays() { | |
Map<String, Object> params = new HashMap<>(); | |
params.put("param1", "Test1"); | |
params.put("param2", new String[]{"Test2"}); | |
Map<String, String[]> result = PortletUrlHelper.ensureParamsAreStringArrays(params); | |
assertEquals(2, result.size()); | |
assertNotNull(result.get("param1")); | |
} | |
public void testSetWindowState() throws Exception { | |
PortletMode mode = PortletMode.VIEW; | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("createRenderURL").will( | |
returnValue(mockPortletUrl.proxy())); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
Map<String, Object> paramMap = new HashMap<>(); | |
paramMap.put(PortletConstants.ACTION_PARAM, new String[]{"/view/testAction"}); | |
paramMap.put(PortletConstants.MODE_PARAM, new String[]{mode.toString()}); | |
mockPortletUrl.expects(once()).method("setParameters").with(new ParamMapConstraint(paramMap)); | |
mockPortletUrl.expects(once()).method("setWindowState").with(eq(WindowState.MAXIMIZED)); | |
mockPortletUrl.expects(once()).method("setPortletMode").with(eq(PortletMode.VIEW)); | |
tag.setAction("testAction"); | |
tag.setWindowState("maximized"); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
} | |
public void testSetPortletMode() throws Exception { | |
PortletMode mode = PortletMode.HELP; | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("createRenderURL").will( | |
returnValue(mockPortletUrl.proxy())); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
Map<String, Object> paramMap = new HashMap<>(); | |
paramMap.put(PortletConstants.ACTION_PARAM, new String[]{"/help/testAction"}); | |
paramMap.put(PortletConstants.MODE_PARAM, new String[]{mode.toString()}); | |
mockPortletUrl.expects(once()).method("setParameters").with(new ParamMapConstraint(paramMap)); | |
mockPortletUrl.expects(once()).method("setPortletMode").with(eq(PortletMode.HELP)); | |
mockPortletUrl.expects(once()).method("setWindowState").with(eq(WindowState.NORMAL)); | |
tag.setNamespace("/help"); | |
tag.setAction("testAction"); | |
tag.setPortletMode("help"); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
} | |
public void testWhenPortletModeDiffersFromCurrentAndNoParametersAreSetRenderTheDefaults() | |
throws Exception { | |
PortletMode mode = PortletMode.HELP; | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("createRenderURL").will( | |
returnValue(mockPortletUrl.proxy())); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
Map<String, Object> paramMap = new HashMap<>(); | |
paramMap.put(PortletConstants.ACTION_PARAM, new String[]{"/help/defaultHelp"}); | |
paramMap.put(PortletConstants.MODE_PARAM, new String[]{mode.toString()}); | |
mockPortletUrl.expects(once()).method("setParameters").with(new ParamMapConstraint(paramMap)); | |
mockPortletUrl.expects(once()).method("setPortletMode").with(eq(PortletMode.HELP)); | |
mockPortletUrl.expects(once()).method("setWindowState").with(eq(WindowState.NORMAL)); | |
tag.setPortletMode("help"); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
} | |
public void testUrlWithQueryParams() throws Exception { | |
PortletMode mode = PortletMode.VIEW; | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("createRenderURL").will( | |
returnValue(mockPortletUrl.proxy())); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
Map<String, Object> paramMap = new HashMap<>(); | |
paramMap.put(PortletConstants.ACTION_PARAM, new String[]{"/view/testAction"}); | |
paramMap.put("testParam1", new String[]{"testValue1"}); | |
paramMap.put(PortletConstants.MODE_PARAM, new String[]{mode.toString()}); | |
mockPortletUrl.expects(once()).method("setParameters").with(new ParamMapConstraint(paramMap)); | |
mockPortletUrl.expects(once()).method("setPortletMode").with(eq(PortletMode.VIEW)); | |
mockPortletUrl.expects(once()).method("setWindowState").with(eq(WindowState.NORMAL)); | |
tag.setAction("testAction?testParam1=testValue1"); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
} | |
public void testActionUrl() throws Exception { | |
PortletMode mode = PortletMode.VIEW; | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("createActionURL").will( | |
returnValue(mockPortletUrl.proxy())); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
Map<String, Object> paramMap = new HashMap<>(); | |
paramMap.put(PortletConstants.ACTION_PARAM, new String[]{"/view/testAction"}); | |
paramMap.put(PortletConstants.MODE_PARAM, new String[]{mode.toString()}); | |
mockPortletUrl.expects(once()).method("setParameters").with(new ParamMapConstraint(paramMap)); | |
mockPortletUrl.expects(once()).method("setPortletMode").with(eq(PortletMode.VIEW)); | |
mockPortletUrl.expects(once()).method("setWindowState").with(eq(WindowState.NORMAL)); | |
tag.setNamespace("/view"); | |
tag.setAction("testAction"); | |
tag.setPortletUrlType("action"); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
} | |
public void testResourceUrl() throws Exception { | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("encodeURL").will(returnValue("/contextPath/image.gif")); | |
mockJspWriter.setExpectedData("/contextPath/image.gif"); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
tag.setValue("image.gif"); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
mockJspWriter.verify(); | |
} | |
public void testResourceUrlWithNestedParam() throws Exception { | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("encodeURL").with(eq("/contextPath/image.gif?testParam1=testValue1")).will(returnValue("/contextPath/image.gif?testParam1=testValue1")); | |
mockJspWriter.setExpectedData("/contextPath/image.gif?testParam1=testValue1"); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
ParamTag paramTag = new ParamTag(); | |
paramTag.setPageContext((PageContext) mockPageCtx.proxy()); | |
paramTag.setParent(tag); | |
paramTag.setName("testParam1"); | |
paramTag.setValue("'testValue1'"); | |
tag.setValue("image.gif"); | |
tag.doStartTag(); | |
paramTag.doStartTag(); | |
paramTag.doEndTag(); | |
tag.doEndTag(); | |
mockJspWriter.verify(); | |
} | |
public void testResourceUrlWithTwoNestedParam() throws Exception { | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("encodeURL").with(eq("/contextPath/image.gif?testParam1=testValue1&testParam2=testValue2")).will(returnValue("/contextPath/image.gif?testParam1=testValue1&testParam2=testValue2")); | |
mockJspWriter.setExpectedData("/contextPath/image.gif?testParam1=testValue1&testParam2=testValue2"); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
ParamTag paramTag = new ParamTag(); | |
paramTag.setPageContext((PageContext) mockPageCtx.proxy()); | |
paramTag.setParent(tag); | |
paramTag.setName("testParam1"); | |
paramTag.setValue("'testValue1'"); | |
ParamTag paramTag2 = new ParamTag(); | |
paramTag2.setPageContext((PageContext) mockPageCtx.proxy()); | |
paramTag2.setParent(tag); | |
paramTag2.setName("testParam2"); | |
paramTag2.setValue("'testValue2'"); | |
tag.setValue("image.gif"); | |
tag.doStartTag(); | |
paramTag.doStartTag(); | |
paramTag.doEndTag(); | |
paramTag2.doStartTag(); | |
paramTag2.doEndTag(); | |
tag.doEndTag(); | |
mockJspWriter.verify(); | |
} | |
public void testUrlWithMethod() throws Exception { | |
PortletMode mode = PortletMode.VIEW; | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("createRenderURL").will( | |
returnValue(mockPortletUrl.proxy())); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
tag.setAction("testAction"); | |
Map<String, Object> paramMap = new HashMap<>(); | |
paramMap.put(PortletConstants.ACTION_PARAM, new String[]{"/view/testAction!input"}); | |
paramMap.put(PortletConstants.MODE_PARAM, new String[]{mode.toString()}); | |
mockPortletUrl.expects(once()).method("setParameters").with(new ParamMapConstraint(paramMap)); | |
mockPortletUrl.expects(once()).method("setPortletMode").with(eq(PortletMode.VIEW)); | |
mockPortletUrl.expects(once()).method("setWindowState").with(eq(WindowState.NORMAL)); | |
tag.setMethod("input"); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
} | |
public void testUrlWithNoActionOrMethod() throws Exception { | |
PortletMode mode = PortletMode.VIEW; | |
mockHttpReq.stubs().method("getQueryString").will(returnValue("")); | |
mockPortletRes.expects(once()).method("createRenderURL").will( | |
returnValue(mockPortletUrl.proxy())); | |
mockCtx.expects(atLeastOnce()).method("getMajorVersion").will(returnValue(1)); | |
Map<String, Object> paramMap = new HashMap<>(); | |
mockActionProxy.stubs().method("getActionName").will(returnValue("currentExecutingAction")); | |
paramMap.put(PortletConstants.ACTION_PARAM, new String[]{"/view/currentExecutingAction"}); | |
paramMap.put(PortletConstants.MODE_PARAM, new String[]{mode.toString()}); | |
mockPortletUrl.expects(once()).method("setParameters").with(new ParamMapConstraint(paramMap)); | |
mockPortletUrl.expects(once()).method("setPortletMode").with(eq(PortletMode.VIEW)); | |
mockPortletUrl.expects(once()).method("setWindowState").with(eq(WindowState.NORMAL)); | |
tag.doStartTag(); | |
tag.doEndTag(); | |
} | |
private static class ParamMapConstraint implements Constraint { | |
private Map<String, Object> myExpectedMap; | |
private Map<String, Object> myActualMap = null; | |
public ParamMapConstraint(Map<String, Object> expectedMap) { | |
if (expectedMap == null) { | |
throw new IllegalArgumentException("Use an isNull constraint instead!"); | |
} | |
myExpectedMap = expectedMap; | |
} | |
/* (non-Javadoc) | |
* @see org.jmock.core.Constraint#eval(java.lang.Object) | |
*/ | |
public boolean eval(Object val) { | |
myActualMap = (Map<String, Object>) val; | |
boolean result = false; | |
if (val != null) { | |
if (myExpectedMap.size() == myActualMap.size()) { | |
Iterator<String> keys = myExpectedMap.keySet().iterator(); | |
boolean allSame = true; | |
while (keys.hasNext()) { | |
Object key = keys.next(); | |
if (!myActualMap.containsKey(key)) { | |
allSame = false; | |
break; | |
} else { | |
String[] expected = (String[]) myExpectedMap.get(key); | |
String[] actual = (String[]) myActualMap.get(key); | |
if (!Arrays.equals(expected, actual)) { | |
allSame = false; | |
break; | |
} | |
} | |
} | |
result = allSame; | |
} | |
} | |
return result; | |
} | |
/* (non-Javadoc) | |
* @see org.jmock.core.SelfDescribing#describeTo(java.lang.StringBuffer) | |
*/ | |
public StringBuffer describeTo(StringBuffer sb) { | |
sb.append("\n Expected: "); | |
describeTo(myExpectedMap, sb); | |
sb.append("\n Actual: "); | |
describeTo(myActualMap, sb); | |
return sb; | |
} | |
private StringBuffer describeTo(Map<String, Object> map, StringBuffer sb) { | |
Iterator<String> it = map.keySet().iterator(); | |
while (it.hasNext()) { | |
String key = it.next(); | |
sb.append(key).append("="); | |
String[] value = (String[]) map.get(key); | |
sb.append(value[0]); | |
if (it.hasNext()) { | |
sb.append(", "); | |
} | |
} | |
return sb; | |
} | |
} | |
} |