View Javadoc

1   /*
2    * $Id: URLTagTest.java 768659 2009-04-26 05:45:28Z wesw $
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.views.jsp;
23  
24  import java.io.File;
25  import java.io.StringWriter;
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import javax.servlet.http.HttpSession;
32  import javax.servlet.jsp.JspWriter;
33  
34  import org.apache.struts2.ServletActionContext;
35  import org.apache.struts2.components.URL;
36  import org.apache.struts2.dispatcher.ApplicationMap;
37  import org.apache.struts2.dispatcher.Dispatcher;
38  import org.apache.struts2.dispatcher.RequestMap;
39  import org.apache.struts2.dispatcher.SessionMap;
40  import org.apache.struts2.dispatcher.mapper.ActionMapping;
41  import org.apache.struts2.dispatcher.mapper.DefaultActionMapper;
42  
43  import com.mockobjects.dynamic.Mock;
44  import com.opensymphony.xwork2.ActionContext;
45  import com.opensymphony.xwork2.ActionProxy;
46  import com.opensymphony.xwork2.DefaultActionInvocation;
47  import com.opensymphony.xwork2.DefaultActionProxy;
48  import com.opensymphony.xwork2.DefaultActionProxyFactory;
49  import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
50  import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
51  import com.opensymphony.xwork2.inject.Container;
52  
53  /***
54   * Unit test for {@link URLTag}.
55   *
56   */
57  public class URLTagTest extends AbstractUITagTest {
58  
59      private URLTag tag;
60  
61  
62      /***
63       * To test priority of parameter passed in to url component though
64       * various way
65       *  - current request url
66       *  - tag's value attribute
67       *  - tag's nested param tag
68       *
69       * id1
70       * ===
71       * - found in current request url
72       * - found in tag's value attribute
73       * - found in tag's param tag
74       * CONCLUSION: tag's param tag takes precedence (paramId1)
75       *
76       * id2
77       * ===
78       * - found in current request url
79       * - found in tag's value attribute
80       * CONCLUSION: tag's value attribute take precedence (tagId2)
81       *
82       * urlParam1
83       * =========
84       * - found in current request url
85       * CONCLUSION: param in current request url will be used (urlValue1)
86       *
87       * urlParam2
88       * =========
89       * - found in current request url
90       * CONCLUSION: param in current request url will be used. (urlValue2)
91       *
92       * tagId
93       * =====
94       * - found in tag's value attribute
95       * CONCLUSION: param in tag's value attribute wil; be used. (tagValue)
96       *
97       * param1
98       * ======
99       * - found in nested param tag
100      * CONCLUSION: param in nested param tag will be used. (param1value)
101      *
102      * param2
103      * ======
104      * - found in nested param tag
105      * CONCLUSION: param in nested param tag will be used. (param2value)
106      */
107     public void testParametersPriority() throws Exception {
108         request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2");
109 
110         tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue");
111 
112         ParamTag param1 = new ParamTag();
113         param1.setPageContext(pageContext);
114         param1.setName("param1");
115         param1.setValue("%{'param1value'}");
116 
117         ParamTag param2 = new ParamTag();
118         param2.setPageContext(pageContext);
119         param2.setName("param2");
120         param2.setValue("%{'param2value'}");
121 
122         ParamTag param3 = new ParamTag();
123         param3.setPageContext(pageContext);
124         param3.setName("id1");
125         param3.setValue("%{'paramId1'}");
126 
127 
128         tag.doStartTag();
129         param1.doStartTag();
130         param1.doEndTag();
131         param2.doStartTag();
132         param2.doEndTag();
133         param3.doStartTag();
134         param3.doEndTag();
135 
136         URL url = (URL) tag.getComponent();
137         Map parameters = url.getParameters();
138 
139 
140         assertNotNull(parameters);
141         assertEquals(parameters.size(), 7);
142         assertEquals(parameters.get("id1"), "paramId1");
143         assertEquals(parameters.get("id2"), "tagId2");
144         assertEquals(parameters.get("urlParam1"), "urlValue1");
145         assertEquals(parameters.get("urlParam2"), "urlValue2");
146         assertEquals(parameters.get("tagId"), "tagValue");
147         assertEquals(parameters.get("param1"), "param1value");
148         assertEquals(parameters.get("param2"), "param2value");
149     }
150 
151     /***
152      * Use Iterable values as the value of the param tags
153      * @throws Exception
154      */
155     public void testIterableParameters() throws Exception {
156         tag.setValue("/TestAction.action?p0=z");
157         
158         tag.doStartTag();
159         //Iterable
160         List<ValueHolder> list = new ArrayList<ValueHolder>();
161         list.add(new ValueHolder("a"));
162         list.add(new ValueHolder("b"));
163         tag.component.addParameter("p1", list);
164         
165         //String[]
166         tag.component.addParameter("p2", new String[] { "d", "e" });
167         //ValueHolder[]
168         tag.component.addParameter("p3", new ValueHolder[] {
169                 new ValueHolder("f"), new ValueHolder("g") });
170         
171         tag.doEndTag();
172         
173         assertEquals("/TestAction.action?p0=z&amp;p1=a&amp;p1=b&amp;p2=d&amp;p2=e&amp;p3=f&amp;p3=g", writer.toString());
174     }
175     
176     /***
177      * To test priority of parameter passed in to url component though
178      * various way, with includeParams="NONE"
179      *  - current request url
180      *  - tag's value attribute
181      *  - tag's nested param tag
182      *
183      *  In this case only parameters from the tag itself is taken into account.
184      *  Those from request will not count, only those in tag's value attribute
185      *  and nested param tag.
186      *
187      * @throws Exception
188      */
189     public void testParametersPriorityWithIncludeParamsAsNONE() throws Exception {
190         request.setQueryString("id1=urlId1&id2=urlId2&urlParam1=urlValue1&urlParam2=urlValue2");
191 
192         tag.setValue("testAction.action?id1=tagId1&id2=tagId2&tagId=tagValue");
193         tag.setIncludeParams("NONE");
194 
195         ParamTag param1 = new ParamTag();
196         param1.setPageContext(pageContext);
197         param1.setName("param1");
198         param1.setValue("%{'param1value'}");
199 
200         ParamTag param2 = new ParamTag();
201         param2.setPageContext(pageContext);
202         param2.setName("param2");
203         param2.setValue("%{'param2value'}");
204 
205         ParamTag param3 = new ParamTag();
206         param3.setPageContext(pageContext);
207         param3.setName("id1");
208         param3.setValue("%{'paramId1'}");
209 
210 
211         tag.doStartTag();
212         param1.doStartTag();
213         param1.doEndTag();
214         param2.doStartTag();
215         param2.doEndTag();
216         param3.doStartTag();
217         param3.doEndTag();
218 
219         URL url = (URL) tag.getComponent();
220         Map parameters = url.getParameters();
221 
222         assertEquals(parameters.size(), 5);
223         assertEquals(parameters.get("id1"), "paramId1");
224         assertEquals(parameters.get("id2"), "tagId2");
225         assertEquals(parameters.get("tagId"), "tagValue");
226         assertEquals(parameters.get("param1"), "param1value");
227         assertEquals(parameters.get("param2"), "param2value");
228     }
229 
230     public void testIncludeParamsDefaultToGET() throws Exception {
231         request.setQueryString("one=oneVal&two=twoVal&three=threeVal");
232 
233         // request parameter map should not have any effect, as includeParams
234         // default to GET, which get its param from request.getQueryString()
235         Map tmp = new HashMap();
236         tmp.put("one", "aaa");
237         tmp.put("two", "bbb");
238         tmp.put("three", "ccc");
239         request.setParameterMap(tmp);
240 
241         tag.setValue("TestAction.acton");
242 
243         tag.doStartTag();
244 
245         URL url = (URL) tag.getComponent();
246         Map parameters = url.getParameters();
247 
248         tag.doEndTag();
249 
250         assertEquals(parameters.get("one"), "oneVal");
251         assertEquals(parameters.get("two"), "twoVal");
252         assertEquals(parameters.get("three"), "threeVal");
253     }
254 
255     public void testActionURL() throws Exception {
256         tag.setValue("TestAction.action");
257 
258         tag.doStartTag();
259         tag.doEndTag();
260         assertEquals("TestAction.action", writer.toString());
261     }
262 
263     public void testAddParameters() throws Exception {
264         request.setAttribute("struts.request_uri", "/Test.action");
265 
266         request.setAttribute("struts.request_uri", "/TestAction.action");
267         request.setQueryString("param0=value0");
268 
269         tag.doStartTag();
270         tag.component.addParameter("param1", "value1");
271         tag.component.addParameter("param2", "value2");
272         tag.doEndTag();
273         assertEquals("/TestAction.action?param0=value0&amp;param1=value1&amp;param2=value2", writer.toString());
274     }
275 
276     public void testEvaluateValue() throws Exception {
277         Foo foo = new Foo();
278         foo.setTitle("test");
279         stack.push(foo);
280         tag.setValue("%{title}");
281 
282         tag.doStartTag();
283         tag.doEndTag();
284         assertEquals("test", writer.toString());
285     }
286 
287     public void testHttps() throws Exception {
288         request.setScheme("https");
289         request.setServerName("localhost");
290         request.setServerPort(443);
291 
292         tag.setValue("list-members.action");
293 
294         tag.doStartTag();
295         tag.doEndTag();
296         assertEquals("list-members.action", writer.toString());
297     }
298 
299     public void testAnchor() throws Exception {
300         request.setScheme("https");
301         request.setServerName("localhost");
302         request.setServerPort(443);
303 
304         tag.setValue("list-members.action");
305         tag.setAnchor("test");
306 
307         tag.doStartTag();
308         tag.doEndTag();
309         assertEquals("list-members.action#test", writer.toString());
310     }
311 
312     public void testParamPrecedence() throws Exception {
313         request.setRequestURI("/context/someAction.action");
314         request.setQueryString("id=22&name=John");
315 
316         URLTag urlTag = new URLTag();
317         urlTag.setPageContext(pageContext);
318         urlTag.setIncludeParams("get");
319         urlTag.setEncode("%{false}");
320 
321         ParamTag paramTag = new ParamTag();
322         paramTag.setPageContext(pageContext);
323         paramTag.setName("id");
324         paramTag.setValue("%{'33'}");
325 
326         urlTag.doStartTag();
327         paramTag.doStartTag();
328         paramTag.doEndTag();
329         urlTag.doEndTag();
330 
331         assertEquals("/context/someAction.action?id=33&amp;name=John", writer.getBuffer().toString());
332     }
333 
334     public void testParamPrecedenceWithAnchor() throws Exception {
335         request.setRequestURI("/context/someAction.action");
336         request.setQueryString("id=22&name=John");
337 
338         URLTag urlTag = new URLTag();
339         urlTag.setPageContext(pageContext);
340         urlTag.setIncludeParams("get");
341         urlTag.setEncode("%{false}");
342         urlTag.setAnchor("testAnchor");
343 
344         ParamTag paramTag = new ParamTag();
345         paramTag.setPageContext(pageContext);
346         paramTag.setName("id");
347         paramTag.setValue("%{'33'}");
348 
349         urlTag.doStartTag();
350         paramTag.doStartTag();
351         paramTag.doEndTag();
352         urlTag.doEndTag();
353 
354         assertEquals("/context/someAction.action?id=33&amp;name=John#testAnchor", writer.getBuffer().toString());
355     }
356 
357     public void testPutId() throws Exception {
358         tag.setValue("/public/about");
359         assertEquals(null, stack.findString("myId")); // nothing in stack
360         tag.setId("myId");
361         tag.doStartTag();
362         tag.doEndTag();
363         assertEquals("", writer.toString());
364         assertEquals("/public/about", stack.findString("myId")); // is in stack now
365     }
366 
367     public void testUsingValueOnly() throws Exception {
368         tag.setValue("/public/about/team.jsp");
369         tag.doStartTag();
370         tag.doEndTag();
371         assertEquals("/public/about/team.jsp", writer.toString());
372     }
373 
374     public void testRequestURIActionIncludeNone() throws Exception {
375         request.setRequestURI("/public/about");
376         request.setQueryString("section=team&company=acme inc");
377 
378         tag.setAction("team");
379         tag.setIncludeParams("none");
380         tag.doStartTag();
381         tag.doEndTag();
382 
383         assertEquals("/team.action", writer.toString());
384     }
385 
386     public void testRequestURIActionIncludeGet() throws Exception {
387         request.setRequestURI("/public/about");
388         request.setQueryString("section=team&company=acme inc");
389 
390         tag.setAction("team");
391         tag.setIncludeParams("get");
392         tag.doStartTag();
393         tag.doEndTag();
394 
395         assertEquals("/team.action?section=team&amp;company=acme+inc", writer.toString());
396     }
397 
398     public void testRequestURIActionIncludeGetDoNotEscapeAmp() throws Exception {
399         request.setRequestURI("/public/about");
400         request.setQueryString("section=team&company=acme inc");
401 
402         tag.setAction("team");
403         tag.setIncludeParams("get");
404         tag.setEscapeAmp("false");
405         tag.doStartTag();
406         tag.doEndTag();
407 
408         assertEquals("/team.action?section=team&company=acme+inc", writer.toString());
409     }
410     
411     public void testRequestURINoActionIncludeNone() throws Exception {
412         request.setRequestURI("/public/about");
413         request.setQueryString("section=team&company=acme inc");
414 
415         tag.setAction(null);
416         tag.setIncludeParams("none");
417         tag.doStartTag();
418         tag.doEndTag();
419 
420         assertEquals("/public/about", writer.toString());
421     }
422 
423     public void testNoActionIncludeGet() throws Exception {
424         request.setRequestURI("/public/about");
425         request.setQueryString("section=team&company=acme inc");
426 
427         tag.setAction(null);
428         tag.setIncludeParams("get");
429         tag.doStartTag();
430         tag.doEndTag();
431 
432         assertEquals("/public/about?section=team&amp;company=acme+inc", writer.toString());
433     }
434 
435     public void testRequestURIActionIncludeAll() throws Exception {
436         request.setRequestURI("/public/about");
437         request.setQueryString("section=team&company=acme inc");
438 
439         tag.setAction("team");
440         tag.setIncludeParams("all");
441 
442         tag.doStartTag();
443 
444         // include nested param tag
445         ParamTag paramTag = new ParamTag();
446         paramTag.setPageContext(pageContext);
447         paramTag.setName("year");
448         paramTag.setValue("2006");
449         paramTag.doStartTag();
450         paramTag.doEndTag();
451 
452         tag.doEndTag();
453 
454         assertEquals("/team.action?section=team&amp;company=acme+inc&amp;year=2006", writer.toString());
455     }
456 
457     public void testRequestURINoActionIncludeAll() throws Exception {
458         request.setRequestURI("/public/about");
459         request.setQueryString("section=team&company=acme inc");
460 
461         tag.setAction(null);
462         tag.setIncludeParams("all");
463 
464         tag.doStartTag();
465 
466         // include nested param tag
467         ParamTag paramTag = new ParamTag();
468         paramTag.setPageContext(pageContext);
469         paramTag.setName("year");
470         paramTag.setValue("2006");
471         paramTag.doStartTag();
472         paramTag.doEndTag();
473 
474         tag.doEndTag();
475 
476         assertEquals("/public/about?section=team&amp;company=acme+inc&amp;year=2006", writer.toString());
477     }
478 
479     public void testUnknownIncludeParam() throws Exception {
480         request.setRequestURI("/public/about");
481         request.setQueryString("section=team");
482 
483         tag.setIncludeParams("unknown"); // will log at WARN level
484         tag.doStartTag();
485         tag.doEndTag();
486         assertEquals("/public/about", writer.toString()); // should not add any request parameters
487     }
488 
489     public void testRequestURIWithAnchor() throws Exception {
490         request.setRequestURI("/public/about");
491         request.setQueryString("company=acme inc#canada");
492 
493         tag.setAction("company");
494         tag.setIncludeParams("get");
495         tag.doStartTag();
496         tag.doEndTag();
497 
498         assertEquals("/company.action?company=acme+inc", writer.toString()); // will always chop anchor if using requestURI
499     }
500 
501     public void testIncludeContext() throws Exception {
502         request.setupGetContext("/myapp");
503 
504         tag.setIncludeContext("true");
505         tag.setAction("company");
506         tag.doStartTag();
507         tag.doEndTag();
508 
509         assertEquals("/myapp/company.action", writer.toString());
510     }
511 
512     public void testForceAddSchemeHostAndPort() throws Exception {
513         tag.setForceAddSchemeHostAndPort("true");
514         tag.setAction("company");
515         tag.doStartTag();
516         tag.doEndTag();
517 
518         assertEquals("http://localhost/company.action", writer.toString());
519     }
520     
521     public void testEmptyActionCustomMapper() throws Exception {
522         Map<String,String> props = new HashMap<String, String>();
523         props.put("config", "struts-default.xml,struts-plugin.xml,struts.xml,org/apache/struts2/views/jsp/WW3090-struts.xml");
524         
525         this.tearDown();
526         
527         Dispatcher du = this.initDispatcher(props);
528         
529         /***
530          * create our standard mock objects
531          */
532         action = this.getAction();
533         stack = ActionContext.getContext().getValueStack();
534         context = stack.getContext();
535         stack.push(action);
536 
537         request = new StrutsMockHttpServletRequest();
538         request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
539         response = new StrutsMockHttpServletResponse();
540         request.setSession(new StrutsMockHttpSession());
541         request.setupGetServletPath("/");
542 
543         writer = new StringWriter();
544 
545         servletContext = new StrutsMockServletContext();
546         servletContext.setRealPath(new File("nosuchfile.properties").getAbsolutePath());
547         servletContext.setServletInfo("Resin");
548 
549         pageContext = new StrutsMockPageContext();
550         pageContext.setRequest(request);
551         pageContext.setResponse(response);
552         pageContext.setServletContext(servletContext);
553 
554         mockContainer = new Mock(Container.class);
555 
556         du.setConfigurationManager(configurationManager);
557         session = new SessionMap(request);
558         Map<String, Object> extraContext = du.createContextMap(new RequestMap(request),
559                 request.getParameterMap(),
560                 session,
561                 new ApplicationMap(pageContext.getServletContext()),
562                 request,
563                 response,
564                 pageContext.getServletContext());
565         // let's not set the locale -- there is a test that checks if Dispatcher actually picks this up...
566         // ... but generally we want to just use no locale (let it stay system default)
567         extraContext.remove(ActionContext.LOCALE);
568         stack.getContext().putAll(extraContext);
569 
570         context.put(ServletActionContext.HTTP_REQUEST, request);
571         context.put(ServletActionContext.HTTP_RESPONSE, response);
572         context.put(ServletActionContext.SERVLET_CONTEXT, servletContext);
573 
574         ActionContext.setContext(new ActionContext(context));
575         
576         // Make sure we have an action invocation available
577         ActionContext.getContext().setActionInvocation(new DefaultActionInvocation(null, true));
578         DefaultActionProxyFactory apFactory = new DefaultActionProxyFactory();
579         apFactory.setContainer(container);
580         ActionProxy ap = apFactory.createActionProxy("/", "hello", null);
581         ActionContext.getContext().getActionInvocation().init(ap);
582 
583         request.setScheme("http");
584         request.setServerName("localhost");
585         request.setServerPort(80);
586 
587         tag = new URLTag();
588         tag.setPageContext(pageContext);
589         JspWriter jspWriter = new StrutsMockJspWriter(writer);
590         pageContext.setJspWriter(jspWriter);
591         
592         request.setRequestURI("/context/someAction.action");
593         
594         tag.setAction(null);
595         tag.setValue(null);
596         tag.doStartTag();
597         tag.doEndTag();
598 
599         assertEquals("/hello.action-red", writer.toString());
600         
601         writer = new StringWriter();
602         jspWriter = new StrutsMockJspWriter(writer);
603         pageContext.setJspWriter(jspWriter);
604         
605         tag.doStartTag();
606         tag.doEndTag();
607         
608         assertEquals("/hello.action-blue", writer.toString());
609         
610         writer = new StringWriter();
611         jspWriter = new StrutsMockJspWriter(writer);
612         pageContext.setJspWriter(jspWriter);
613         
614         tag.doStartTag();
615         tag.doEndTag();
616         
617         assertEquals("/hello.action-red", writer.toString());
618         
619         
620     }
621 
622     protected void setUp() throws Exception {
623         super.setUp();
624 
625         request.setScheme("http");
626         request.setServerName("localhost");
627         request.setServerPort(80);
628 
629         tag = new URLTag();
630         tag.setPageContext(pageContext);
631         JspWriter jspWriter = new StrutsMockJspWriter(writer);
632         pageContext.setJspWriter(jspWriter);
633     }
634 
635     public static class Foo {
636         private String title;
637 
638         public void setTitle(String title) {
639             this.title = title;
640         }
641 
642         public String getTitle() {
643             return title;
644         }
645 
646         public String toString() {
647             return "Foo is: " + title;
648         }
649     }
650     
651     public static class ValueHolder {
652         private String value;
653 
654         public ValueHolder(String value) {
655             this.value = value;
656         }
657 
658         @Override
659         public String toString() {
660             return value;
661         }
662         
663         
664     }
665     
666     public static class RedBlueActionMapper extends DefaultActionMapper {
667         
668         @Override
669         public String getUriFromActionMapping(ActionMapping mapping) {
670             String baseUri = super.getUriFromActionMapping(mapping);
671             HttpSession session = ServletActionContext.getRequest().getSession();
672             if (session.getAttribute("redBlue")==null) {
673                 // We are red
674                 session.setAttribute("redBlue", 0);
675                 return baseUri + "-red";
676             } else {
677                 // We are blue
678                 session.removeAttribute("redBlue");
679                 return baseUri + "-blue";
680             }
681         }
682         
683     }
684 }