001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry.engine;
016    
017    import org.apache.hivemind.ApplicationRuntimeException;
018    import org.apache.hivemind.Location;
019    import org.apache.tapestry.*;
020    import org.apache.tapestry.event.BrowserEvent;
021    import org.apache.tapestry.services.LinkFactory;
022    import org.apache.tapestry.services.ResponseRenderer;
023    import org.apache.tapestry.services.ServiceConstants;
024    import org.apache.tapestry.web.WebRequest;
025    import org.apache.tapestry.web.WebSession;
026    import static org.easymock.EasyMock.*;
027    import org.testng.annotations.Test;
028    
029    import java.util.Collections;
030    import java.util.HashMap;
031    import java.util.Map;
032    
033    /**
034     * Tests for {@link org.apache.tapestry.engine.DirectService}.
035     */
036    @Test
037    public class DirectServiceTest extends ServiceTestCase
038    {
039        protected IDirect newDirect(boolean checkParameters)
040        {
041            IDirect c = newMock(IDirect.class);
042            
043            if (checkParameters) {
044                checkOrder(c, false);
045    
046                expect(c.getUpdateComponents()).andReturn(Collections.EMPTY_LIST);
047                expect(c.isJson()).andReturn(false);
048                expect(c.isAsync()).andReturn(false);
049                expect(c.isStateful()).andReturn(true);
050            }
051            
052            return c;
053        }
054    
055        public void test_Get_Link_On_Same_Page()
056        {
057            IPage page = newPage("ThePage");
058            IDirect c = newDirect(true);
059            IRequestCycle cycle = newCycle();
060            WebRequest request = newWebRequest(false, null);
061            LinkFactory lf = newLinkFactory();
062            ILink link = newLink();
063    
064            trainGetPage(cycle, page);
065            trainGetPage(c, page);
066            trainGetIdPath(c, "fred.barney");
067    
068            Object[] serviceParameters = new Object[0];
069    
070            Map parameters = new HashMap();
071    
072            parameters.put(ServiceConstants.PAGE, "ThePage");
073            parameters.put(ServiceConstants.COMPONENT, "fred.barney");
074            parameters.put(ServiceConstants.CONTAINER, null);
075            parameters.put(ServiceConstants.SESSION, null);
076            parameters.put(ServiceConstants.PARAMETER, serviceParameters);
077    
078            DirectService ds = new DirectService();
079    
080            ds.setLinkFactory(lf);
081            ds.setRequest(request);
082            ds.setRequestCycle(cycle);
083    
084            trainConstructLink(lf, ds, false, parameters, true, link);
085    
086            replay();
087    
088            assertSame(link, ds.getLink(false, new DirectServiceParameter(c, serviceParameters)));
089    
090            verify();
091        }
092    
093        public void test_Get_Link_On_Same_Page_For_Post()
094        {
095            IPage page = newPage("ThePage");
096            IDirect c = newDirect(true);
097            IRequestCycle cycle = newCycle();
098            WebRequest request = newWebRequest(false, null);
099            LinkFactory lf = newLinkFactory();
100            ILink link = newLink();
101    
102            trainGetPage(cycle, page);
103            trainGetPage(c, page);
104            trainGetIdPath(c, "fred.barney");
105    
106            Object[] serviceParameters = new Object[0];
107    
108            Map parameters = new HashMap();
109    
110            parameters.put(ServiceConstants.PAGE, "ThePage");
111            parameters.put(ServiceConstants.COMPONENT, "fred.barney");
112            parameters.put(ServiceConstants.CONTAINER, null);
113            parameters.put(ServiceConstants.SESSION, null);
114            parameters.put(ServiceConstants.PARAMETER, serviceParameters);
115    
116            DirectService ds = new DirectService();
117    
118            ds.setLinkFactory(lf);
119            ds.setRequest(request);
120            ds.setRequestCycle(cycle);
121    
122            trainConstructLink(lf, ds, true, parameters, true, link);
123    
124            replay();
125    
126            assertSame(link, ds.getLink(true, new DirectServiceParameter(c, serviceParameters)));
127    
128            verify();
129        }
130    
131        public void test_Get_Link_On_Same_Page_Stateful()
132        {   
133            IDirect c = newDirect(true);
134            
135            IPage page = newPage("ThePage");
136            IRequestCycle cycle = newCycle();
137            WebSession session = newWebSession();
138            WebRequest request = newWebRequest(false, session);
139            LinkFactory lf = newLinkFactory();
140            ILink link = newLink();
141            
142            trainGetPage(cycle, page);
143            trainGetPage(c, page);
144            trainGetIdPath(c, "fred.barney");
145    
146            Object[] serviceParameters = new Object[0];
147    
148            Map parameters = new HashMap();
149    
150            parameters.put(ServiceConstants.PAGE, "ThePage");
151            parameters.put(ServiceConstants.COMPONENT, "fred.barney");
152            parameters.put(ServiceConstants.CONTAINER, null);
153            parameters.put(ServiceConstants.SESSION, "T");
154            parameters.put(ServiceConstants.PARAMETER, serviceParameters);
155    
156            DirectService ds = new DirectService();
157            ds.setLinkFactory(lf);
158            ds.setRequest(request);
159            ds.setRequestCycle(cycle);
160            
161            trainConstructLink(lf, ds, false, parameters, true, link);
162            
163            replay();
164            
165            assertSame(link, ds.getLink(false, new DirectServiceParameter(c, serviceParameters)));
166    
167            verify();
168        }
169    
170        public void test_Get_Link_On_Different_Page()
171        {
172            IPage page = newPage("ActivePage");
173            IPage componentPage = newPage("ComponentPage");
174            IDirect c = newDirect(true);
175            IRequestCycle cycle = newCycle();
176            WebRequest request = newWebRequest(false, null);
177            LinkFactory lf = newLinkFactory();
178            ILink link = newLink();
179    
180            trainGetPage(cycle, page);
181            trainGetPage(c, componentPage);
182            trainGetIdPath(c, "fred.barney");
183    
184            Object[] serviceParameters = new Object[0];
185    
186            Map parameters = new HashMap();
187    
188            parameters.put(ServiceConstants.PAGE, "ActivePage");
189            parameters.put(ServiceConstants.COMPONENT, "fred.barney");
190            parameters.put(ServiceConstants.CONTAINER, "ComponentPage");
191            parameters.put(ServiceConstants.SESSION, null);
192            parameters.put(ServiceConstants.PARAMETER, serviceParameters);
193    
194            DirectService ds = new DirectService();
195            ds.setLinkFactory(lf);
196            ds.setRequest(request);
197            ds.setRequestCycle(cycle);
198    
199            trainConstructLink(lf, ds, false, parameters, true, link);
200    
201            replay();
202    
203            assertSame(link, ds.getLink(false, new DirectServiceParameter(c, serviceParameters)));
204    
205            verify();
206        }
207    
208        public void test_Service_Simple() throws Exception
209        {
210            Object[] parameters = new Object[0];
211            IRequestCycle cycle = newCycle();
212            IPage page = newPage();
213            IDirect d = newDirect(false);
214            LinkFactory lf = newLinkFactory();
215            ResponseRenderer rr = newResponseRenderer();
216    
217            trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
218            trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
219            trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
220            trainGetParameter(cycle, ServiceConstants.SESSION, null);
221    
222            trainGetPage(cycle, "ActivePage", page);
223            cycle.activate(page);
224    
225            trainGetNestedComponent(page, "fred.barney", d);
226    
227            trainExtractListenerParameters(lf, cycle, parameters);
228            
229            expect(cycle.getParameter(BrowserEvent.NAME)).andReturn(null);
230            
231            cycle.setListenerParameters(parameters);
232    
233            d.trigger(cycle);
234    
235            rr.renderResponse(cycle);
236    
237            replay();
238    
239            DirectService ds = new DirectService();
240            ds.setLinkFactory(lf);
241            ds.setResponseRenderer(rr);
242    
243            ds.service(cycle);
244    
245            verify();
246        }
247    
248        public void test_Service_Simple_Event() throws Exception
249        {
250            Object[] parameters = new Object[0];
251            IRequestCycle cycle = newCycle();
252            IPage page = newPage();
253            IDirect d = newDirect(false);
254            LinkFactory lf = newLinkFactory();
255            ResponseRenderer rr = newResponseRenderer();
256    
257            trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
258            trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
259            trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
260            trainGetParameter(cycle, ServiceConstants.SESSION, null);
261    
262            trainGetPage(cycle, "ActivePage", page);
263            cycle.activate(page);
264            trainGetNestedComponent(page, "fred.barney", d);
265    
266            trainExtractListenerParameters(lf, cycle, parameters);
267            trainExtractBrowserEvent(cycle);
268            
269            cycle.setListenerParameters(isA(Object[].class));
270            
271            d.trigger(cycle);
272    
273            rr.renderResponse(cycle);
274    
275            replay();
276    
277            DirectService ds = new DirectService();
278            ds.setLinkFactory(lf);
279            ds.setResponseRenderer(rr);
280    
281            ds.service(cycle);
282    
283            verify();
284        }
285        
286        /**
287         * The complex case is where the component is contained on a different page than the active (at
288         * the time of render) page.
289         */
290        public void test_Service_Complex() throws Exception
291        {
292            Object[] parameters = new Object[0];
293            IRequestCycle cycle = newCycle();
294            IPage page = newPage();
295            IPage componentPage = newPage();
296            IDirect d = newDirect(false);
297            LinkFactory lf = newLinkFactory();
298            ResponseRenderer rr = newResponseRenderer();
299    
300            trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
301            trainGetParameter(cycle, ServiceConstants.CONTAINER, "ComponentPage");
302            trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
303            trainGetParameter(cycle, ServiceConstants.SESSION, null);
304    
305            trainGetPage(cycle, "ActivePage", page);
306    
307            cycle.activate(page);
308    
309            trainGetPage(cycle, "ComponentPage", componentPage);
310    
311            trainGetNestedComponent(componentPage, "fred.barney", d);
312    
313            trainExtractListenerParameters(lf, cycle, parameters);
314            
315            expect(cycle.getParameter(BrowserEvent.NAME)).andReturn(null);
316            
317            cycle.setListenerParameters(parameters);
318    
319            d.trigger(cycle);
320    
321            rr.renderResponse(cycle);
322    
323            replay();
324    
325            DirectService ds = new DirectService();
326            ds.setLinkFactory(lf);
327            ds.setResponseRenderer(rr);
328    
329            ds.service(cycle);
330    
331            verify();
332        }
333    
334        public void test_Service_Not_Direct() throws Exception
335        {
336            IRequestCycle cycle = newCycle();
337            IPage page = newPage();
338            IComponent c = newComponent();
339            Location l = newLocation();
340    
341            trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
342            trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
343            trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
344            trainGetParameter(cycle, ServiceConstants.SESSION, null);
345    
346            trainGetPage(cycle, "ActivePage", page);
347            cycle.activate(page);
348    
349            trainGetNestedComponent(page, "fred.barney", c);
350    
351            trainGetExtendedId(c, "ActivePage/fred.barney");
352            trainGetLocation(c, l);
353    
354            replay();
355    
356            DirectService ds = new DirectService();
357    
358            try
359            {
360                ds.service(cycle);
361                unreachable();
362            }
363            catch (ApplicationRuntimeException ex)
364            {
365                assertEquals(
366                        "Component ActivePage/fred.barney does not implement the org.apache.tapestry.IDirect interface.",
367                        ex.getMessage());
368                assertSame(c, ex.getComponent());
369                assertSame(l, ex.getLocation());
370            }
371    
372            verify();
373        }
374    
375        public void test_Session_Active_And_Required() throws Exception
376        {
377            Object[] parameters = new Object[0];
378            IRequestCycle cycle = newCycle();
379            IPage page = newPage();
380            IDirect d = newDirect(false);
381            
382            LinkFactory lf = newLinkFactory();
383            ResponseRenderer rr = newResponseRenderer();
384    
385            trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
386            trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
387            trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
388            trainGetParameter(cycle, ServiceConstants.SESSION, "T");
389    
390            trainGetPage(cycle, "ActivePage", page);
391            cycle.activate(page);
392    
393            trainGetNestedComponent(page, "fred.barney", d);
394    
395            trainIsStateful(d, true);
396    
397            WebSession session = newMock(WebSession.class);
398            WebRequest request = newWebRequest(session);
399            
400            expect(session.isNew()).andReturn(false);
401            
402            trainExtractListenerParameters(lf, cycle, parameters);
403            
404            expect(cycle.getParameter(BrowserEvent.NAME)).andReturn(null);
405            
406            cycle.setListenerParameters(parameters);
407    
408            d.trigger(cycle);
409    
410            rr.renderResponse(cycle);
411    
412            replay();
413    
414            DirectService ds = new DirectService();
415            ds.setLinkFactory(lf);
416            ds.setResponseRenderer(rr);
417            ds.setRequest(request);
418    
419            ds.service(cycle);
420    
421            verify();
422        }
423    
424        protected void trainIsStateful(IDirect direct, boolean isStateful)
425        {
426            expect(direct.isStateful()).andReturn(isStateful);
427        }
428    
429        public void test_Stale_Session() throws Exception
430        {
431            IRequestCycle cycle = newCycle();
432            IPage page = newPage();
433            IDirect d = newDirect(false);
434            
435            Location l = newLocation();
436    
437            trainGetParameter(cycle, ServiceConstants.COMPONENT, "fred.barney");
438            trainGetParameter(cycle, ServiceConstants.CONTAINER, null);
439            trainGetParameter(cycle, ServiceConstants.PAGE, "ActivePage");
440            trainGetParameter(cycle, ServiceConstants.SESSION, "T");
441    
442            trainGetPage(cycle, "ActivePage", page);
443            cycle.activate(page);
444    
445            trainGetNestedComponent(page, "fred.barney", d);
446    
447            trainIsStateful(d, true);
448            
449            WebRequest request = newWebRequest(null);
450            
451            trainGetExtendedId(d, "ActivePage/fred.barney");
452            trainGetLocation(page, l);
453            trainGetPageName(page, "ActivePage");
454    
455            replay();
456    
457            DirectService ds = new DirectService();
458            ds.setRequest(request);
459    
460            try
461            {
462                ds.service(cycle);
463                unreachable();
464            }
465            catch (StaleSessionException ex)
466            {
467                assertEquals(
468                        "Component ActivePage/fred.barney is stateful, but the HttpSession has expired (or has not yet been created).",
469                        ex.getMessage());
470                assertSame(page, ex.getComponent());
471                assertSame(l, ex.getLocation());
472                assertEquals("ActivePage", ex.getPageName());
473                assertSame(page, ex.getPage());
474            }
475    
476            verify();
477        }
478    }