1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.portlet.dispatcher;
23
24 import java.io.File;
25 import java.util.Collections;
26 import java.util.HashMap;
27 import java.util.Iterator;
28 import java.util.ListResourceBundle;
29 import java.util.Locale;
30 import java.util.Map;
31
32 import javax.portlet.ActionRequest;
33 import javax.portlet.ActionResponse;
34 import javax.portlet.PortletConfig;
35 import javax.portlet.PortletContext;
36 import javax.portlet.PortletMode;
37 import javax.portlet.PortletSession;
38 import javax.portlet.RenderRequest;
39 import javax.portlet.RenderResponse;
40 import javax.portlet.WindowState;
41
42 import org.apache.struts2.StrutsConstants;
43 import org.apache.struts2.dispatcher.mapper.ActionMapping;
44 import org.apache.struts2.portlet.PortletActionConstants;
45 import org.easymock.EasyMock;
46 import org.jmock.Mock;
47 import org.jmock.cglib.MockObjectTestCase;
48 import org.jmock.core.Constraint;
49 import org.springframework.mock.web.portlet.MockActionRequest;
50 import org.springframework.mock.web.portlet.MockActionResponse;
51 import org.springframework.mock.web.portlet.MockPortletConfig;
52 import org.springframework.mock.web.portlet.MockPortletContext;
53
54 import com.opensymphony.xwork2.Action;
55 import com.opensymphony.xwork2.ActionContext;
56 import com.opensymphony.xwork2.ActionInvocation;
57 import com.opensymphony.xwork2.ActionProxy;
58 import com.opensymphony.xwork2.ActionProxyFactory;
59 import com.opensymphony.xwork2.util.ValueStack;
60
61 /***
62 * Jsr168DispatcherTest. Insert description.
63 *
64 */
65 public class Jsr168DispatcherTest extends MockObjectTestCase implements PortletActionConstants {
66
67 private final String MULTIPART_REQUEST = "-----------------------------4827543632391\r\n"
68 + "Content-Disposition: form-data; name=\"upload\"; filename=\"test.txt\"\r\n"
69 + "Content-Type: text/plain\r\n"
70 + "\r\n"
71 + "This is a test file\r\n"
72 + "-----------------------------4827543632391\r\n"
73 + "Content-Disposition: form-data; name=\"caption\"\r\n"
74 + "\r\n"
75 + "TestCaption\r\n" + "-----------------------------4827543632391--";
76
77 Jsr168Dispatcher dispatcher = null;
78
79 Mock mockConfig = null;
80
81 Mock mockCtx = null;
82
83 Mock mockRequest = null;
84
85 Mock mockSession = null;
86
87 Mock mockActionFactory = null;
88
89 Mock mockActionProxy = null;
90
91 Mock mockAction = null;
92
93 Mock mockInvocation = null;
94
95 public void setUp() throws Exception {
96 super.setUp();
97 dispatcher = new Jsr168Dispatcher();
98 }
99
100 private void initPortletConfig(final Map<String, String> initParams, final Map<String, Object> attributes) {
101 mockConfig = mock(PortletConfig.class);
102 mockCtx = mock(PortletContext.class);
103 mockConfig.stubs().method(ANYTHING);
104 mockCtx.stubs().method(ANYTHING);
105 setupStub(initParams, mockConfig, "getInitParameter");
106 mockCtx.stubs().method("getAttributeNames").will(returnValue(Collections.enumeration(attributes.keySet())));
107 setupStub(attributes, mockCtx, "getAttribute");
108 mockConfig.stubs().method("getPortletContext").will(returnValue(mockCtx.proxy()));
109 mockCtx.stubs().method("getInitParameterNames").will(returnValue(Collections.enumeration(initParams.keySet())));
110 setupStub(initParams, mockCtx, "getInitParameter");
111 mockConfig.stubs().method("getInitParameterNames").will(
112 returnValue(Collections.enumeration(initParams.keySet())));
113 setupStub(initParams, mockConfig, "getInitParameter");
114 mockConfig.stubs().method("getResourceBundle").will(returnValue(new ListResourceBundle() {
115 protected Object[][] getContents() {
116 return new String[][] { { "javax.portlet.title", "MyTitle" } };
117 }
118 }));
119 }
120
121 private void setupActionFactory(String namespace, String actionName, String result, ValueStack stack) {
122 if (mockActionFactory == null) {
123 mockActionFactory = mock(ActionProxyFactory.class);
124 }
125 mockAction = mock(Action.class);
126 mockActionProxy = mock(ActionProxy.class);
127 mockInvocation = mock(ActionInvocation.class);
128
129 mockActionFactory.expects(once()).method("createActionProxy").with(
130 new Constraint[] { eq(namespace), eq(actionName), NULL, isA(Map.class) }).will(
131 returnValue(mockActionProxy.proxy()));
132 mockActionProxy.stubs().method("getAction").will(returnValue(mockAction.proxy()));
133 mockActionProxy.expects(once()).method("execute").will(returnValue(result));
134 mockActionProxy.expects(once()).method("getInvocation").will(returnValue(mockInvocation.proxy()));
135 mockInvocation.stubs().method("getStack").will(returnValue(stack));
136
137 }
138
139 public void testParseConfigWithBang() {
140 MockPortletContext portletContext = new MockPortletContext();
141 MockPortletConfig portletConfig = new MockPortletConfig(portletContext);
142
143 portletConfig.addInitParameter("viewNamespace", "/view");
144 portletConfig.addInitParameter("defaultViewAction", "index!input");
145
146 Map<PortletMode, ActionMapping> actionMap = new HashMap<PortletMode, ActionMapping>();
147
148 dispatcher.parseModeConfig(actionMap, portletConfig, PortletMode.VIEW, "viewNamespace", "defaultViewAction");
149
150 ActionMapping mapping = actionMap.get(PortletMode.VIEW);
151 assertEquals("index", mapping.getName());
152 assertEquals("/view", mapping.getNamespace());
153 assertEquals("input", mapping.getMethod());
154 }
155
156 public void testRender_ok() throws Exception {
157 final Mock mockResponse = mock(RenderResponse.class);
158 mockResponse.stubs().method(ANYTHING);
159
160 PortletMode mode = PortletMode.VIEW;
161
162 Map<String, String[]> requestParams = new HashMap<String, String[]>();
163 requestParams.put(PortletActionConstants.ACTION_PARAM, new String[] { "/view/testAction" });
164 requestParams.put(EVENT_ACTION, new String[] { "true" });
165 requestParams.put(PortletActionConstants.MODE_PARAM, new String[] { mode.toString() });
166
167 Map sessionMap = new HashMap();
168
169 Map<String, String> initParams = new HashMap<String, String>();
170 initParams.put("viewNamespace", "/view");
171 initParams.put(StrutsConstants.STRUTS_ALWAYS_SELECT_FULL_NAMESPACE, "true");
172
173 initPortletConfig(initParams, new HashMap<String, Object>());
174 initRequest(requestParams, new HashMap(), sessionMap, new HashMap(), PortletMode.VIEW, WindowState.NORMAL,
175 false, null);
176 setupActionFactory("/view", "testAction", "success", EasyMock.createNiceMock(ValueStack.class));
177
178 mockInvocation.expects(once()).method("getStack").will(returnValue(null));
179
180
181
182 dispatcher.setActionProxyFactory((ActionProxyFactory) mockActionFactory.proxy());
183 dispatcher.init((PortletConfig) mockConfig.proxy());
184 dispatcher.render((RenderRequest) mockRequest.proxy(), (RenderResponse) mockResponse.proxy());
185 }
186
187 public void testProcessAction_ok() throws Exception {
188 final Mock mockResponse = mock(ActionResponse.class);
189
190 PortletMode mode = PortletMode.VIEW;
191 Map<String, String> initParams = new HashMap<String, String>();
192 initParams.put("viewNamespace", "/view");
193
194 Map<String, String[]> requestParams = new HashMap<String, String[]>();
195 requestParams.put(PortletActionConstants.ACTION_PARAM, new String[] { "/view/testAction" });
196 requestParams.put(PortletActionConstants.MODE_PARAM, new String[] { mode.toString() });
197
198 initParams.put(StrutsConstants.STRUTS_ALWAYS_SELECT_FULL_NAMESPACE, "true");
199 initPortletConfig(initParams, new HashMap<String, Object>());
200 initRequest(requestParams, new HashMap<String, Object>(), new HashMap<String, Object>(), new HashMap<String, String[]>(), PortletMode.VIEW, WindowState.NORMAL,
201 true, null);
202 setupActionFactory("/view", "testAction", "success", EasyMock.createNiceMock(ValueStack.class));
203
204
205
206 dispatcher.setActionProxyFactory((ActionProxyFactory) mockActionFactory.proxy());
207 dispatcher.init((PortletConfig) mockConfig.proxy());
208 dispatcher.processAction((ActionRequest) mockRequest.proxy(), (ActionResponse) mockResponse.proxy());
209 }
210
211 /***
212 * Initialize the mock request (and as a result, the mock session)
213 *
214 * @param requestParams
215 * The request parameters
216 * @param requestAttributes
217 * The request attributes
218 * @param sessionParams
219 * The session attributes
220 * @param renderParams
221 * The render parameters. Will only be set if
222 * <code>isEvent</code> is <code>true</code>
223 * @param mode
224 * The portlet mode
225 * @param state
226 * The portlet window state
227 * @param isEvent
228 * <code>true</code> when the request is an ActionRequest.
229 * @param locale
230 * The locale. If <code>null</code>, the request will return
231 * <code>Locale.getDefault()</code>
232 */
233 private void initRequest(Map<String, String[]> requestParams, Map<String, Object> requestAttributes, Map<String, Object> sessionParams, Map<String, String[]> renderParams,
234 PortletMode mode, WindowState state, boolean isEvent, Locale locale) {
235 mockRequest = isEvent ? mock(ActionRequest.class) : mock(RenderRequest.class);
236 mockSession = mock(PortletSession.class);
237 mockSession.stubs().method(ANYTHING);
238 mockRequest.stubs().method(ANYTHING);
239 setupStub(sessionParams, mockSession, "getAttribute");
240 mockSession.stubs().method("getAttributeNames").will(
241 returnValue(Collections.enumeration(sessionParams.keySet())));
242 setupParamStub(requestParams, mockRequest, "getParameter");
243 setupStub(requestAttributes, mockRequest, "getAttribute");
244 mockRequest.stubs().method("getAttributeNames").will(
245 returnValue(Collections.enumeration(requestAttributes.keySet())));
246 mockRequest.stubs().method("getParameterMap").will(returnValue(requestParams));
247 mockRequest.stubs().method("getParameterNames").will(
248 returnValue(Collections.enumeration(requestParams.keySet())));
249 mockRequest.stubs().method("getPortletSession").will(returnValue(mockSession.proxy()));
250 if (locale != null) {
251 mockRequest.stubs().method("getLocale").will(returnValue(locale));
252 } else {
253 mockRequest.stubs().method("getLocale").will(returnValue(Locale.getDefault()));
254 }
255 mockRequest.stubs().method("getPortletMode").will(returnValue(mode));
256 mockRequest.stubs().method("getWindowState").will(returnValue(state));
257 }
258
259 private void setupParamStub(Map<String, String[]> requestParams, Mock mockRequest, String method) {
260 Map<String, String> newMap = new HashMap<String, String>();
261 Iterator<String> it = requestParams.keySet().iterator();
262 while (it.hasNext()) {
263 String key = it.next();
264 String[] val = (String[]) requestParams.get(key);
265 newMap.put(key, val[0]);
266 }
267 setupStub(newMap, mockRequest, method);
268
269 }
270
271 /***
272 * Set up stubs for the mock.
273 *
274 * @param map
275 * The map containing the <code>key</code> and
276 * <code>values</code>. The key is the expected parameter to
277 * <code>method</code>, and value is the value that should be
278 * returned from the stub.
279 * @param mock
280 * The mock to initialize.
281 * @param method
282 * The name of the method to stub.
283 */
284 private void setupStub(Map map, Mock mock, String method) {
285 Iterator it = map.keySet().iterator();
286 while (it.hasNext()) {
287 Object key = it.next();
288 Object val = map.get(key);
289 mock.stubs().method(method).with(eq(key)).will(returnValue(val));
290 }
291 }
292
293 public void testModeChangeUsingPortletWidgets() throws Exception {
294 final Mock mockResponse = mock(RenderResponse.class);
295 mockResponse.stubs().method(ANYTHING);
296 PortletMode mode = PortletMode.EDIT;
297
298 Map<String, String[]> requestParams = new HashMap<String, String[]>();
299 requestParams.put(PortletActionConstants.ACTION_PARAM, new String[] { "/view/testAction" });
300 requestParams.put(EVENT_ACTION, new String[] { "false" });
301 requestParams.put(PortletActionConstants.MODE_PARAM, new String[] { PortletMode.VIEW.toString() });
302
303 Map<String, Object> sessionMap = new HashMap<String, Object>();
304
305 Map<String, String> initParams = new HashMap<String, String>();
306 initParams.put("viewNamespace", "/view");
307 initParams.put("editNamespace", "/edit");
308
309 initPortletConfig(initParams, new HashMap<String, Object>());
310 initRequest(requestParams, new HashMap<String, Object>(), sessionMap, new HashMap<String, String[]>(), mode, WindowState.NORMAL, false, null);
311 setupActionFactory("/edit", "default", "success", EasyMock.createNiceMock(ValueStack.class));
312
313 mockInvocation.expects(once()).method("getStack").will(returnValue(null));
314
315
316
317 dispatcher.setActionProxyFactory((ActionProxyFactory) mockActionFactory.proxy());
318 dispatcher.init((PortletConfig) mockConfig.proxy());
319 dispatcher.render((RenderRequest) mockRequest.proxy(), (RenderResponse) mockResponse.proxy());
320 }
321
322 public void testMultipartRequest_parametersAreCopiedToActionInvocation() throws Exception {
323 MockPortletContext ctx = new MockPortletContext();
324 ctx.setAttribute("javax.servlet.context.tempdir", new File("target").getAbsoluteFile());
325 MockActionRequest request = new MockActionRequest(ctx);
326 request.setContent(MULTIPART_REQUEST.getBytes("US-ASCII"));
327 request.setContentType("multipart/form-data; boundary=---------------------------4827543632391");
328 request.setProperty("Content-Length", "" + MULTIPART_REQUEST.length());
329 MockActionResponse response = new MockActionResponse();
330 Map<String, Object> requestMap = new HashMap<String, Object>();
331 Map<String, String[]> paramMap = new HashMap<String, String[]>();
332 Map<String, Object> sessionMap = new HashMap<String, Object>();
333 Map<String, Object> applicationMap = new HashMap<String, Object>();
334 initPortletConfig(new HashMap<String, String>(), new HashMap<String, Object>());
335 MockPortletConfig config = new MockPortletConfig(ctx);
336 dispatcher.init(config);
337 dispatcher.createContextMap(requestMap, paramMap, sessionMap, applicationMap, request, response, config,
338 PortletActionConstants.EVENT_PHASE);
339 assertNotNull("Caption was not found in parameter map!", paramMap.get("caption"));
340 assertEquals("TestCaption", paramMap.get("caption")[0]);
341 }
342 }