1 /*
2  * Copyright 2008 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package org.springframework.web.servlet.tags;
18 
19 import java.io.UnsupportedEncodingException;
20 import java.lang.reflect.Method;
21 import java.net.URLDecoder;
22 import java.util.HashSet;
23 import java.util.LinkedList;
24 import java.util.List;
25 import java.util.Set;
26 
27 import javax.servlet.jsp.JspException;
28 import javax.servlet.jsp.PageContext;
29 import javax.servlet.jsp.tagext.Tag;
30 
31 import org.springframework.mock.web.MockHttpServletRequest;
32 import org.springframework.mock.web.MockPageContext;
33 import org.springframework.util.ReflectionUtils;
34 
35 /**
36  * Unit tests for UrlTag
37  *
38  * @author Scott Andrews
39  */
40 public class UrlTagTests extends AbstractTagTests {
41 
42 	private UrlTag tag;
43 
44 	private MockPageContext context;
45 
46 	@Override
setUp()47 	protected void setUp() throws Exception {
48 		context = createPageContext();
49 		tag = new UrlTag();
50 		tag.setPageContext(context);
51 	}
52 
testParamSupport()53 	public void testParamSupport() {
54 		assertTrue(tag instanceof ParamAware);
55 	}
56 
testDoStartTag()57 	public void testDoStartTag() throws JspException {
58 		int action = tag.doStartTag();
59 
60 		assertEquals(Tag.EVAL_BODY_INCLUDE, action);
61 	}
62 
testDoEndTag()63 	public void testDoEndTag() throws JspException {
64 		tag.setValue("url/path");
65 
66 		tag.doStartTag();
67 		int action = tag.doEndTag();
68 
69 		assertEquals(Tag.EVAL_PAGE, action);
70 	}
71 
testVarDefaultScope()72 	public void testVarDefaultScope() throws JspException {
73 		tag.setValue("url/path");
74 		tag.setVar("var");
75 
76 		tag.doStartTag();
77 		tag.doEndTag();
78 
79 		assertEquals("url/path", context.getAttribute("var",
80 				PageContext.PAGE_SCOPE));
81 	}
82 
testVarExplicitScope()83 	public void testVarExplicitScope() throws JspException {
84 		tag.setValue("url/path");
85 		tag.setVar("var");
86 		tag.setScope("request");
87 
88 		tag.doStartTag();
89 		tag.doEndTag();
90 
91 		assertEquals("url/path", context.getAttribute("var",
92 				PageContext.REQUEST_SCOPE));
93 	}
94 
testSetHtmlEscapeDefault()95 	public void testSetHtmlEscapeDefault() throws JspException {
96 		tag.setValue("url/path");
97 		tag.setVar("var");
98 
99 		tag.doStartTag();
100 
101 		Param param = new Param();
102 		param.setName("n me");
103 		param.setValue("v&l=e");
104 		tag.addParam(param);
105 
106 		param = new Param();
107 		param.setName("name");
108 		param.setValue("value2");
109 		tag.addParam(param);
110 
111 		tag.doEndTag();
112 
113 		assertEquals("url/path?n%20me=v%26l%3De&name=value2", context
114 				.getAttribute("var"));
115 	}
116 
testSetHtmlEscapeFalse()117 	public void testSetHtmlEscapeFalse() throws JspException {
118 		tag.setValue("url/path");
119 		tag.setVar("var");
120 		tag.setHtmlEscape("false");
121 
122 		tag.doStartTag();
123 
124 		Param param = new Param();
125 		param.setName("n me");
126 		param.setValue("v&l=e");
127 		tag.addParam(param);
128 
129 		param = new Param();
130 		param.setName("name");
131 		param.setValue("value2");
132 		tag.addParam(param);
133 
134 		tag.doEndTag();
135 
136 		assertEquals("url/path?n%20me=v%26l%3De&name=value2", context
137 				.getAttribute("var"));
138 	}
139 
testSetHtmlEscapeTrue()140 	public void testSetHtmlEscapeTrue() throws JspException {
141 		tag.setValue("url/path");
142 		tag.setVar("var");
143 		tag.setHtmlEscape("true");
144 
145 		tag.doStartTag();
146 
147 		Param param = new Param();
148 		param.setName("n me");
149 		param.setValue("v&l=e");
150 		tag.addParam(param);
151 
152 		param = new Param();
153 		param.setName("name");
154 		param.setValue("value2");
155 		tag.addParam(param);
156 
157 		tag.doEndTag();
158 
159 		assertEquals("url/path?n%20me=v%26l%3De&name=value2", context
160 				.getAttribute("var"));
161 	}
162 
testSetJavaScriptEscapeTrue()163 	public void testSetJavaScriptEscapeTrue() throws JspException {
164 		tag.setValue("url/path");
165 		tag.setVar("var");
166 		tag.setJavaScriptEscape("true");
167 
168 		tag.doStartTag();
169 
170 		Param param = new Param();
171 		param.setName("n me");
172 		param.setValue("v&l=e");
173 		tag.addParam(param);
174 
175 		param = new Param();
176 		param.setName("name");
177 		param.setValue("value2");
178 		tag.addParam(param);
179 
180 		tag.doEndTag();
181 
182 		assertEquals("url\\/path?n%20me=v%26l%3De&name=value2", context
183 				.getAttribute("var"));
184 	}
185 
testSetHtmlAndJavaScriptEscapeTrue()186 	public void testSetHtmlAndJavaScriptEscapeTrue() throws JspException {
187 		tag.setValue("url/path");
188 		tag.setVar("var");
189 		tag.setHtmlEscape("true");
190 		tag.setJavaScriptEscape("true");
191 
192 		tag.doStartTag();
193 
194 		Param param = new Param();
195 		param.setName("n me");
196 		param.setValue("v&l=e");
197 		tag.addParam(param);
198 
199 		param = new Param();
200 		param.setName("name");
201 		param.setValue("value2");
202 		tag.addParam(param);
203 
204 		tag.doEndTag();
205 
206 		assertEquals("url\\/path?n%20me=v%26l%3De&name=value2", context
207 				.getAttribute("var"));
208 	}
209 
testCreateQueryStringNoParams()210 	public void testCreateQueryStringNoParams() throws JspException {
211 		List<Param> params = new LinkedList<Param>();
212 		Set<String> usedParams = new HashSet<String>();
213 
214 		String queryString = tag.createQueryString(params, usedParams, true);
215 
216 		assertEquals("", queryString);
217 	}
218 
testCreateQueryStringOneParam()219 	public void testCreateQueryStringOneParam() throws JspException {
220 		List<Param> params = new LinkedList<Param>();
221 		Set<String> usedParams = new HashSet<String>();
222 
223 		Param param = new Param();
224 		param.setName("name");
225 		param.setValue("value");
226 		params.add(param);
227 
228 		String queryString = tag.createQueryString(params, usedParams, true);
229 
230 		assertEquals("?name=value", queryString);
231 	}
232 
testCreateQueryStringOneParamForExsistingQueryString()233 	public void testCreateQueryStringOneParamForExsistingQueryString()
234 			throws JspException {
235 		List<Param> params = new LinkedList<Param>();
236 		Set<String> usedParams = new HashSet<String>();
237 
238 		Param param = new Param();
239 		param.setName("name");
240 		param.setValue("value");
241 		params.add(param);
242 
243 		String queryString = tag.createQueryString(params, usedParams, false);
244 
245 		assertEquals("&name=value", queryString);
246 	}
247 
testCreateQueryStringOneParamEmptyValue()248 	public void testCreateQueryStringOneParamEmptyValue() throws JspException {
249 		List<Param> params = new LinkedList<Param>();
250 		Set<String> usedParams = new HashSet<String>();
251 
252 		Param param = new Param();
253 		param.setName("name");
254 		param.setValue("");
255 		params.add(param);
256 
257 		String queryString = tag.createQueryString(params, usedParams, true);
258 
259 		assertEquals("?name=", queryString);
260 	}
261 
testCreateQueryStringOneParamNullValue()262 	public void testCreateQueryStringOneParamNullValue() throws JspException {
263 		List<Param> params = new LinkedList<Param>();
264 		Set<String> usedParams = new HashSet<String>();
265 
266 		Param param = new Param();
267 		param.setName("name");
268 		param.setValue(null);
269 		params.add(param);
270 
271 		String queryString = tag.createQueryString(params, usedParams, true);
272 
273 		assertEquals("?name", queryString);
274 	}
275 
testCreateQueryStringOneParamAlreadyUsed()276 	public void testCreateQueryStringOneParamAlreadyUsed() throws JspException {
277 		List<Param> params = new LinkedList<Param>();
278 		Set<String> usedParams = new HashSet<String>();
279 
280 		Param param = new Param();
281 		param.setName("name");
282 		param.setValue("value");
283 		params.add(param);
284 
285 		usedParams.add("name");
286 
287 		String queryString = tag.createQueryString(params, usedParams, true);
288 
289 		assertEquals("", queryString);
290 	}
291 
testCreateQueryStringTwoParams()292 	public void testCreateQueryStringTwoParams() throws JspException {
293 		List<Param> params = new LinkedList<Param>();
294 		Set<String> usedParams = new HashSet<String>();
295 
296 		Param param = new Param();
297 		param.setName("name");
298 		param.setValue("value");
299 		params.add(param);
300 
301 		param = new Param();
302 		param.setName("name");
303 		param.setValue("value2");
304 		params.add(param);
305 
306 		String queryString = tag.createQueryString(params, usedParams, true);
307 
308 		assertEquals("?name=value&name=value2", queryString);
309 	}
310 
testCreateQueryStringUrlEncoding()311 	public void testCreateQueryStringUrlEncoding() throws JspException {
312 		List<Param> params = new LinkedList<Param>();
313 		Set<String> usedParams = new HashSet<String>();
314 
315 		Param param = new Param();
316 		param.setName("n me");
317 		param.setValue("v&l=e");
318 		params.add(param);
319 
320 		param = new Param();
321 		param.setName("name");
322 		param.setValue("value2");
323 		params.add(param);
324 
325 		String queryString = tag.createQueryString(params, usedParams, true);
326 
327 		assertEquals("?n%20me=v%26l%3De&name=value2", queryString);
328 	}
329 
testCreateQueryStringParamNullName()330 	public void testCreateQueryStringParamNullName() throws JspException {
331 		List<Param> params = new LinkedList<Param>();
332 		Set<String> usedParams = new HashSet<String>();
333 
334 		Param param = new Param();
335 		param.setName(null);
336 		param.setValue("value");
337 		params.add(param);
338 
339 		String queryString = tag.createQueryString(params, usedParams, true);
340 
341 		assertEquals("", queryString);
342 	}
343 
testCreateQueryStringParamEmptyName()344 	public void testCreateQueryStringParamEmptyName() throws JspException {
345 		List<Param> params = new LinkedList<Param>();
346 		Set<String> usedParams = new HashSet<String>();
347 
348 		Param param = new Param();
349 		param.setName("");
350 		param.setValue("value");
351 		params.add(param);
352 
353 		String queryString = tag.createQueryString(params, usedParams, true);
354 
355 		assertEquals("", queryString);
356 	}
357 
testReplaceUriTemplateParamsNoParams()358 	public void testReplaceUriTemplateParamsNoParams() throws JspException {
359 		List<Param> params = new LinkedList<Param>();
360 		Set<String> usedParams = new HashSet<String>();
361 
362 		String uri = tag.replaceUriTemplateParams("url/path", params,
363 				usedParams);
364 
365 		assertEquals("url/path", uri);
366 		assertEquals(0, usedParams.size());
367 	}
368 
testReplaceUriTemplateParamsTemplateWithoutParamMatch()369 	public void testReplaceUriTemplateParamsTemplateWithoutParamMatch()
370 			throws JspException {
371 		List<Param> params = new LinkedList<Param>();
372 		Set<String> usedParams = new HashSet<String>();
373 
374 		String uri = tag.replaceUriTemplateParams("url/{path}", params,
375 				usedParams);
376 
377 		assertEquals("url/{path}", uri);
378 		assertEquals(0, usedParams.size());
379 	}
380 
testReplaceUriTemplateParamsTemplateWithParamMatch()381 	public void testReplaceUriTemplateParamsTemplateWithParamMatch()
382 			throws JspException {
383 		List<Param> params = new LinkedList<Param>();
384 		Set<String> usedParams = new HashSet<String>();
385 
386 		Param param = new Param();
387 		param.setName("name");
388 		param.setValue("value");
389 		params.add(param);
390 
391 		String uri = tag.replaceUriTemplateParams("url/{name}", params,
392 				usedParams);
393 
394 		assertEquals("url/value", uri);
395 		assertEquals(1, usedParams.size());
396 		assertTrue(usedParams.contains("name"));
397 	}
398 
testReplaceUriTemplateParamsTemplateWithParamMatchNamePreEncoding()399 	public void testReplaceUriTemplateParamsTemplateWithParamMatchNamePreEncoding()
400 			throws JspException {
401 		List<Param> params = new LinkedList<Param>();
402 		Set<String> usedParams = new HashSet<String>();
403 
404 		Param param = new Param();
405 		param.setName("n me");
406 		param.setValue("value");
407 		params.add(param);
408 
409 		String uri = tag.replaceUriTemplateParams("url/{n me}", params,
410 				usedParams);
411 
412 		assertEquals("url/value", uri);
413 		assertEquals(1, usedParams.size());
414 		assertTrue(usedParams.contains("n me"));
415 	}
416 
testReplaceUriTemplateParamsTemplateWithParamMatchValueEncoded()417 	public void testReplaceUriTemplateParamsTemplateWithParamMatchValueEncoded()
418 			throws JspException {
419 		List<Param> params = new LinkedList<Param>();
420 		Set<String> usedParams = new HashSet<String>();
421 
422 		Param param = new Param();
423 		param.setName("name");
424 		param.setValue("v lue");
425 		params.add(param);
426 
427 		String uri = tag.replaceUriTemplateParams("url/{name}", params,
428 				usedParams);
429 
430 		assertEquals("url/v%20lue", uri);
431 		assertEquals(1, usedParams.size());
432 		assertTrue(usedParams.contains("name"));
433 	}
434 
testCreateUrlRemoteServer()435 	public void testCreateUrlRemoteServer() throws JspException {
436 		tag.setValue("http://www.springframework.org/");
437 
438 		tag.doStartTag();
439 
440 		// String uri = tag.createUrl();
441 		String uri = invokeCreateUrl(tag);
442 
443 		assertEquals("http://www.springframework.org/", uri);
444 	}
445 
testCreateUrlRelative()446 	public void testCreateUrlRelative() throws JspException {
447 		tag.setValue("url/path");
448 
449 		tag.doStartTag();
450 
451 		String uri = invokeCreateUrl(tag);
452 
453 		assertEquals("url/path", uri);
454 	}
455 
testCreateUrlLocalContext()456 	public void testCreateUrlLocalContext() throws JspException {
457 		((MockHttpServletRequest) context.getRequest())
458 				.setContextPath("/app-context");
459 
460 		tag.setValue("/url/path");
461 
462 		tag.doStartTag();
463 
464 		String uri = invokeCreateUrl(tag);
465 
466 		assertEquals("/app-context/url/path", uri);
467 	}
468 
testCreateUrlRemoteContext()469 	public void testCreateUrlRemoteContext() throws JspException {
470 		((MockHttpServletRequest) context.getRequest())
471 				.setContextPath("/app-context");
472 
473 		tag.setValue("/url/path");
474 		tag.setContext("some-other-context");
475 
476 		tag.doStartTag();
477 
478 		String uri = invokeCreateUrl(tag);
479 
480 		assertEquals("/some-other-context/url/path", uri);
481 	}
482 
testCreateUrlRemoteContextWithSlash()483 	public void testCreateUrlRemoteContextWithSlash() throws JspException {
484 		((MockHttpServletRequest) context.getRequest())
485 				.setContextPath("/app-context");
486 
487 		tag.setValue("/url/path");
488 		tag.setContext("/some-other-context");
489 
490 		tag.doStartTag();
491 
492 		String uri = invokeCreateUrl(tag);
493 
494 		assertEquals("/some-other-context/url/path", uri);
495 	}
496 
testCreateUrlWithParams()497 	public void testCreateUrlWithParams() throws JspException {
498 		tag.setValue("url/path");
499 
500 		tag.doStartTag();
501 
502 		Param param = new Param();
503 		param.setName("name");
504 		param.setValue("value");
505 		tag.addParam(param);
506 
507 		param = new Param();
508 		param.setName("n me");
509 		param.setValue("v lue");
510 		tag.addParam(param);
511 
512 		String uri = invokeCreateUrl(tag);
513 
514 		assertEquals("url/path?name=value&n%20me=v%20lue", uri);
515 	}
516 
testCreateUrlWithTemplateParams()517 	public void testCreateUrlWithTemplateParams() throws JspException {
518 		tag.setValue("url/{name}");
519 
520 		tag.doStartTag();
521 
522 		Param param = new Param();
523 		param.setName("name");
524 		param.setValue("value");
525 		tag.addParam(param);
526 
527 		param = new Param();
528 		param.setName("n me");
529 		param.setValue("v lue");
530 		tag.addParam(param);
531 
532 		String uri = invokeCreateUrl(tag);
533 
534 		assertEquals("url/value?n%20me=v%20lue", uri);
535 	}
536 
testCreateUrlWithParamAndExsistingQueryString()537 	public void testCreateUrlWithParamAndExsistingQueryString()
538 			throws JspException {
539 		tag.setValue("url/path?foo=bar");
540 
541 		tag.doStartTag();
542 
543 		Param param = new Param();
544 		param.setName("name");
545 		param.setValue("value");
546 		tag.addParam(param);
547 
548 		String uri = invokeCreateUrl(tag);
549 
550 		assertEquals("url/path?foo=bar&name=value", uri);
551 	}
552 
testJspWriterOutput()553 	public void testJspWriterOutput() {
554 		// TODO assert that the output to the JspWriter is the expected output
555 	}
556 
testServletRepsonseEncodeUrl()557 	public void testServletRepsonseEncodeUrl() {
558 		// TODO assert that HttpServletResponse.encodeURL(String) is invoked for
559 		// non absolute urls
560 	}
561 
562 	// support methods
563 
invokeCreateUrl(UrlTag tag)564 	private String invokeCreateUrl(UrlTag tag) {
565 		Method createUrl = ReflectionUtils.findMethod(tag.getClass(),
566 				"createUrl");
567 		ReflectionUtils.makeAccessible(createUrl);
568 		return (String) ReflectionUtils.invokeMethod(createUrl, tag);
569 	}
570 
571 }
572