diff --git a/plugins/portlet/src/main/java/org/apache/struts2/components/PortletUrlRenderer.java b/plugins/portlet/src/main/java/org/apache/struts2/components/PortletUrlRenderer.java index 55ae052a5..3d5056efb 100644 --- a/plugins/portlet/src/main/java/org/apache/struts2/components/PortletUrlRenderer.java +++ b/plugins/portlet/src/main/java/org/apache/struts2/components/PortletUrlRenderer.java @@ -20,6 +20,8 @@ */ package org.apache.struts2.components; +import com.opensymphony.xwork2.ActionContext; +import com.opensymphony.xwork2.ActionInvocation; import com.opensymphony.xwork2.util.TextUtils; import org.apache.struts2.StrutsException; import org.apache.struts2.portlet.util.PortletUrlHelper; @@ -46,11 +48,14 @@ public class PortletUrlRenderer implements UrlRenderer { } String result; - if (urlComponent.value == null && urlComponent.action != null) { + if (onlyActionSpecified(urlComponent)) { result = PortletUrlHelper.buildUrl(urlComponent.action, urlComponent.namespace, urlComponent.method, urlComponent.parameters, urlComponent.portletUrlType, urlComponent.portletMode, urlComponent.windowState); - } else { + } else if(onlyValueSpecified(urlComponent)){ result = PortletUrlHelper.buildResourceUrl(urlComponent.value, urlComponent.parameters); } + else { + result = createDefaultUrl(urlComponent); + } if ( urlComponent.anchor != null && urlComponent.anchor.length() > 0 ) { result += '#' + urlComponent.anchor; } @@ -71,15 +76,35 @@ public class PortletUrlRenderer implements UrlRenderer { } } + private String createDefaultUrl(URL urlComponent) { + String result; + ActionInvocation ai = (ActionInvocation)urlComponent.getStack().getContext().get( + ActionContext.ACTION_INVOCATION); + String action = ai.getProxy().getActionName(); + result = PortletUrlHelper.buildUrl(action, urlComponent.namespace, urlComponent.method, urlComponent.parameters, urlComponent.portletUrlType, urlComponent.portletMode, urlComponent.windowState); + return result; + } + + private boolean onlyValueSpecified(URL urlComponent) { + return urlComponent.value != null && urlComponent.action == null; + } + + private boolean onlyActionSpecified(URL urlComponent) { + return urlComponent.value == null && urlComponent.action != null; + } + /** * {@inheritDoc} */ public void renderFormUrl(Form formComponent) { String action = null; if (formComponent.action != null) { - // if it isn't specified, we'll make somethig up action = formComponent.findString(formComponent.action); } + else { + ActionInvocation ai = (ActionInvocation) formComponent.getStack().getContext().get(ActionContext.ACTION_INVOCATION); + action = ai.getProxy().getActionName(); + } String type = "action"; if (TextUtils.stringSet(formComponent.method)) { diff --git a/plugins/portlet/src/test/java/org/apache/struts2/views/jsp/PortletUrlTagTest.java b/plugins/portlet/src/test/java/org/apache/struts2/views/jsp/PortletUrlTagTest.java index d6a4c32df..1d4d670f5 100644 --- a/plugins/portlet/src/test/java/org/apache/struts2/views/jsp/PortletUrlTagTest.java +++ b/plugins/portlet/src/test/java/org/apache/struts2/views/jsp/PortletUrlTagTest.java @@ -20,7 +20,6 @@ */ package org.apache.struts2.views.jsp; -import java.lang.reflect.Field; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; @@ -48,11 +47,14 @@ import org.jmock.core.Constraint; 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; /** */ +@SuppressWarnings("unchecked") public class PortletUrlTagTest extends MockObjectTestCase { URLTag tag = new URLTag(); @@ -84,8 +86,6 @@ public class PortletUrlTagTest extends MockObjectTestCase { du.init(); Dispatcher.setInstance(du); - mockPortletApiAvailable(); - stack = du.getContainer().getInstance(ValueStackFactory.class).createValueStack(); stack.getContext().put(ActionContext.CONTAINER, du.getContainer()); ActionContext.setContext(new ActionContext(stack.getContext())); @@ -138,21 +138,6 @@ public class PortletUrlTagTest extends MockObjectTestCase { ActionContext.setContext(ctx); } - /** - * - */ - private void mockPortletApiAvailable() { - try { - Field field = Dispatcher.class.getDeclaredField("portletSupportActive"); - field.setAccessible(true); - field.set(null, Boolean.TRUE); - } - catch(Exception e) { - - } - - } - public void testEnsureParamsAreStringArrays() { Map params = new HashMap(); params.put("param1", "Test1"); @@ -326,6 +311,31 @@ public class PortletUrlTagTest extends MockObjectTestCase { tag.doEndTag(); } + public void testUrlWithNoActionOrMethod() throws Exception { + PortletMode mode = PortletMode.VIEW; + mockHttpReq.stubs().method("getQueryString").will(returnValue("")); + mockPortletRes.expects(once()).method("createRenderURL").will( + returnValue((PortletURL) mockPortletUrl.proxy())); + Map paramMap = new HashMap(); + + Mock mockActionProxy = mock(ActionProxy.class); + mockActionProxy.stubs().method("getActionName").will(returnValue("currentExecutingAction")); + final ActionProxy proxy = (ActionProxy)mockActionProxy.proxy(); + + Mock mockActionInvocation = mock(ActionInvocation.class); + mockActionInvocation.stubs().method("getProxy").will(returnValue(proxy)); + ActionInvocation ai = (ActionInvocation)mockActionInvocation.proxy(); + + stack.getContext().put(ActionContext.ACTION_INVOCATION, ai); + paramMap.put(PortletActionConstants.ACTION_PARAM, new String[]{"/view/currentExecutingAction"}); + paramMap.put(PortletActionConstants.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 myExpectedMap = null;