View Javadoc

1   /*
2    * $Id: Jsr168DispatcherTest.java 671156 2008-06-24 12:33:59Z nilsga $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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 		// mockSession.expects(once()).method("setAttribute").with(new
180 		// Constraint[]{eq(PortletActionConstants.LAST_MODE),
181 		// eq(PortletMode.VIEW)});
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 		// mockSession.expects(once()).method("setAttribute").with(new
204 		// Constraint[]{eq(PortletActionConstants.LAST_MODE),
205 		// eq(PortletMode.VIEW)});
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 		// mockSession.expects(once()).method("setAttribute").with(new
315 		// Constraint[]{eq(PortletActionConstants.LAST_MODE),
316 		// eq(PortletMode.VIEW)});
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 }