001    // Copyright 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.resolver;
016    
017    import org.apache.commons.logging.Log;
018    import org.apache.hivemind.ApplicationRuntimeException;
019    import org.apache.hivemind.Location;
020    import org.apache.hivemind.Resource;
021    import org.apache.tapestry.INamespace;
022    import org.apache.tapestry.IRequestCycle;
023    import org.apache.tapestry.PageNotFoundException;
024    import org.apache.tapestry.Tapestry;
025    import org.apache.tapestry.engine.ISpecificationSource;
026    import org.apache.tapestry.services.ComponentPropertySource;
027    import org.apache.tapestry.spec.ComponentSpecification;
028    import org.apache.tapestry.spec.IComponentSpecification;
029    import org.apache.tapestry.spec.ILibrarySpecification;
030    import static org.easymock.EasyMock.checkOrder;
031    import static org.easymock.EasyMock.expect;
032    import org.testng.annotations.Test;
033    
034    import java.util.List;
035    
036    /**
037     * Tests for {@link org.apache.tapestry.resolver.PageSpecificationResolverImpl}.
038     * 
039     * @author Howard M. Lewis Ship
040     * @since 4.0
041     */
042    @Test
043    public class PageSpecificationResolverTest extends AbstractSpecificationResolverTestCase
044    {
045        public static class MockApplicationNamespace implements INamespace
046        {
047            String _pageName;
048    
049            IComponentSpecification _specification;
050    
051            private Resource _specificationLocation;
052    
053            MockApplicationNamespace(Resource specificationLocation)
054            {
055                _specificationLocation = specificationLocation;
056            }
057    
058            public String constructQualifiedName(String pageName)
059            {
060                return null;
061            }
062    
063            public boolean containsComponentType(String type)
064            {
065                return false;
066            }
067    
068            public boolean containsPage(String name)
069            {
070                return false;
071            }
072    
073            public List getChildIds()
074            {
075                return null;
076            }
077    
078            public INamespace getChildNamespace(String id)
079            {
080                return null;
081            }
082    
083            public IComponentSpecification getComponentSpecification(String type)
084            {
085                return null;
086            }
087    
088            public String getExtendedId()
089            {
090                return null;
091            }
092    
093            public String getId()
094            {
095                return null;
096            }
097    
098            public Location getLocation()
099            {
100                return null;
101            }
102    
103            public String getNamespaceId()
104            {
105                return null;
106            }
107    
108            public List getPageNames()
109            {
110                return null;
111            }
112    
113            public IComponentSpecification getPageSpecification(String name)
114            {
115                return null;
116            }
117    
118            public INamespace getParentNamespace()
119            {
120                return null;
121            }
122    
123            public String getPropertyValue(String propertyName)
124            {
125                return null;
126            }
127    
128            public ILibrarySpecification getSpecification()
129            {
130                return null;
131            }
132    
133            public Resource getSpecificationLocation()
134            {
135                return _specificationLocation;
136            }
137    
138            public void installComponentSpecification(String type, IComponentSpecification specification)
139            {
140            }
141    
142            public void installPageSpecification(String pageName, IComponentSpecification specification)
143            {
144                _pageName = pageName;
145                _specification = specification;
146            }
147    
148            public boolean isApplicationNamespace()
149            {
150                return true;
151            }
152    
153        }
154    
155        protected ISpecificationResolverDelegate newDelegate()
156        {
157            return newMock(ISpecificationResolverDelegate.class);
158        }
159    
160        protected INamespace newNamespace(String pageName, IComponentSpecification spec)
161        {
162            INamespace namespace = newNamespace();
163            checkOrder(namespace, false);
164            
165            trainContainsPage(namespace, pageName, spec != null);
166    
167            if (spec != null)
168                trainGetPageSpecification(namespace, pageName, spec);
169    
170            return namespace;
171        }
172    
173        protected ComponentPropertySource newPropertySource(INamespace namespace)
174        {
175            ComponentPropertySource source = newMock(ComponentPropertySource.class);
176    
177            expect(source.getNamespaceProperty(namespace, Tapestry.TEMPLATE_EXTENSION_PROPERTY))
178            .andReturn("html");
179    
180            return source;
181        }
182    
183        protected ISpecificationSource newSource(INamespace application, INamespace framework)
184        {
185            ISpecificationSource source = newSource();
186    
187            trainGetApplicationNamespace(source, application);
188    
189            trainGetFrameworkNamespace(source, framework);
190    
191            return source;
192        }
193    
194        protected ISpecificationSource newSource(INamespace application, INamespace framework,
195                Resource resource, IComponentSpecification pageSpec)
196        {
197            ISpecificationSource source = newSource();
198            checkOrder(source, false);
199            
200            trainGetApplicationNamespace(source, application);
201    
202            trainGetFrameworkNamespace(source, framework);
203    
204            trainGetPageSpecification(source, resource, pageSpec);
205    
206            return source;
207        }
208    
209        public void test_Explicitly_In_Application_Namespace()
210        {
211            Resource contextRoot = newResource("context/");
212            IComponentSpecification spec = newSpecification();
213            INamespace application = newNamespace("ExistingPage", spec);
214            INamespace framework = newNamespace();
215    
216            ISpecificationSource source = newSource();
217    
218            trainGetApplicationNamespace(source, application);
219            trainGetFrameworkNamespace(source, framework);
220    
221            IRequestCycle cycle = newCycle();
222    
223            trainGetApplicationNamespace(source, application);
224    
225            replay();
226    
227            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
228            resolver.setContextRoot(contextRoot);
229            resolver.setSpecificationSource(source);
230            resolver.initializeService();
231    
232            resolver.resolve(cycle, "application:ExistingPage");
233    
234            assertEquals("ExistingPage", resolver.getSimplePageName());
235            assertSame(spec, resolver.getSpecification());
236            assertSame(application, resolver.getNamespace());
237    
238            verify();
239    
240        }
241    
242        public void test_Explicitly_In_Framework_Namespace()
243        {
244            Resource contextRoot = newResource("context/");
245            IComponentSpecification spec = newSpecification();
246            INamespace application = newNamespace();
247            INamespace framework = newNamespace("ExistingPage", spec);
248            
249            ISpecificationSource source = newSource();
250            
251            trainGetApplicationNamespace(source, application);
252            trainGetFrameworkNamespace(source, framework);
253    
254            IRequestCycle cycle = newCycle();
255    
256            trainGetFrameworkNamespace(source, framework);
257    
258            replay();
259    
260            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
261            resolver.setContextRoot(contextRoot);
262            resolver.setSpecificationSource(source);
263            resolver.initializeService();
264    
265            resolver.resolve(cycle, "framework:ExistingPage");
266    
267            assertEquals("ExistingPage", resolver.getSimplePageName());
268            assertSame(spec, resolver.getSpecification());
269            assertSame(framework, resolver.getNamespace());
270    
271            verify();
272        }
273    
274        public void test_Found_As_Template()
275        {
276            Log log = newLog();
277    
278            Resource contextRoot = newResource("context/");
279    
280            Resource resource = contextRoot.getRelativeResource("TemplatePage.html");
281    
282            MockApplicationNamespace application = new MockApplicationNamespace(contextRoot
283                    .getRelativeResource("WEB-INF/"));
284    
285            INamespace framework = newNamespace();
286            ISpecificationSource source = newSource(application, framework);
287            IRequestCycle cycle = newCycle();
288            
289            train(log, ResolverMessages.resolvingPage("TemplatePage", application));
290    
291            train(log, ResolverMessages.checkingResource(contextRoot
292                    .getRelativeResource("WEB-INF/TemplatePage.page")));
293            
294            train(log, ResolverMessages.checkingResource(contextRoot
295                    .getRelativeResource("WEB-INF/myapp/TemplatePage.page")));
296            train(log, ResolverMessages.checkingResource(contextRoot
297                    .getRelativeResource("WEB-INF/TemplatePage.page")));
298            
299            train(log, ResolverMessages.checkingResource(contextRoot
300                    .getRelativeResource("TemplatePage.page")));
301            
302            ComponentPropertySource propertySource = newPropertySource(application);
303            
304            train(log, ResolverMessages.checkingResource(contextRoot
305                    .getRelativeResource("TemplatePage.html")));
306            
307            train(log, ResolverMessages.foundHTMLTemplate(resource));
308            
309            IComponentSpecification expectedSpec = new ComponentSpecification();
310            expectedSpec.setPageSpecification(true);
311            expectedSpec.setSpecificationLocation(resource);
312            
313            // The toString() on ComponentSpecification means we can't predict
314            // what the string would be.
315            
316            trainIsDebugEnabled(log, false);
317            
318            replay();
319            
320            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
321            resolver.setContextRoot(contextRoot);
322            resolver.setSpecificationSource(source);
323            resolver.setLog(log);
324            resolver.setApplicationId("myapp");
325            resolver.setComponentPropertySource(propertySource);
326    
327            resolver.initializeService();
328    
329            resolver.resolve(cycle, "TemplatePage");
330    
331            IComponentSpecification spec = application._specification;
332    
333            assertEquals(true, spec.isPageSpecification());
334    
335            // The specification location is used to find relative assets and the like, and is baesd
336            // on the page name and the namespace location.
337    
338            assertEquals(contextRoot.getRelativeResource("WEB-INF/TemplatePage.page"), spec
339                    .getSpecificationLocation());
340    
341            // The Location is used for any error reporting, and should be the actual file
342            // located, the template.
343    
344            assertEquals(resource, spec.getLocation().getResource());
345            assertEquals("TemplatePage", resolver.getSimplePageName());
346            assertEquals("TemplatePage", application._pageName);
347    
348            assertSame(spec, resolver.getSpecification());
349            assertSame(application, resolver.getNamespace());
350    
351            verify();
352        }
353    
354        public void test_Found_In_Application_Namespace()
355        {
356            Resource contextRoot = newResource("context/");
357            IComponentSpecification spec = newSpecification();
358            INamespace application = newNamespace("ExistingPage", spec);
359            INamespace framework = newNamespace();
360            ISpecificationSource source = newSource(application, framework);
361            IRequestCycle cycle = newCycle();
362    
363            replay();
364    
365            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
366            resolver.setContextRoot(contextRoot);
367            resolver.setSpecificationSource(source);
368            resolver.initializeService();
369    
370            resolver.resolve(cycle, "ExistingPage");
371    
372            assertEquals("ExistingPage", resolver.getSimplePageName());
373            assertSame(spec, resolver.getSpecification());
374            assertSame(application, resolver.getNamespace());
375    
376            verify();
377        }
378    
379        public void test_Found_In_Child_Namespace()
380        {
381            Resource contextRoot = newResource("context/");
382            IComponentSpecification spec = newSpecification();
383    
384            INamespace child = newNamespace("ChildPage", spec);
385            INamespace application = newNamespace();
386    
387            trainGetChildNamespace(child, "foo.bar", application);
388    
389            INamespace framework = newNamespace();
390            ISpecificationSource source = newSource(application, framework);
391            IRequestCycle cycle = newCycle();
392    
393            replay();
394    
395            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
396            resolver.setContextRoot(contextRoot);
397            resolver.setSpecificationSource(source);
398            resolver.initializeService();
399    
400            resolver.resolve(cycle, "foo.bar:ChildPage");
401    
402            assertEquals("ChildPage", resolver.getSimplePageName());
403            assertSame(spec, resolver.getSpecification());
404            assertSame(child, resolver.getNamespace());
405    
406            verify();
407        }
408    
409        public void test_Found_In_ContextRoot_Folder()
410        {
411            Log log = newLog();
412    
413            Resource contextRoot = newResource("context/");
414            IComponentSpecification spec = newSpecification();
415            
416            Resource resource = contextRoot.getRelativeResource("ContextRootPage.page");
417            
418            INamespace application = newNamespace();
419            
420            INamespace framework = newNamespace();
421            
422            ISpecificationSource source = newSource(application, framework, resource, spec);
423            
424            trainContainsPage(application, "ContextRootPage", false);
425            
426            IRequestCycle cycle = newCycle();
427    
428            train(log, ResolverMessages.resolvingPage("ContextRootPage", application));
429    
430            // Pretend the app spec is in the WEB-INF folder
431    
432            trainGetSpecificationLocation(application, contextRoot, "WEB-INF/");
433    
434            train(log, ResolverMessages.checkingResource(contextRoot
435                    .getRelativeResource("WEB-INF/ContextRootPage.page")));
436    
437            trainIsApplicationNamespace(application, true);
438    
439            train(log, ResolverMessages.checkingResource(contextRoot
440                    .getRelativeResource("WEB-INF/myapp/ContextRootPage.page")));
441            train(log, ResolverMessages.checkingResource(contextRoot
442                    .getRelativeResource("WEB-INF/ContextRootPage.page")));
443            train(log, ResolverMessages.checkingResource(resource));
444    
445            train(log, ResolverMessages.installingPage("ContextRootPage", application, spec));
446    
447            application.installPageSpecification("ContextRootPage", spec);
448    
449            replay();
450    
451            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
452            resolver.setContextRoot(contextRoot);
453            resolver.setSpecificationSource(source);
454            resolver.setLog(log);
455            resolver.setApplicationId("myapp");
456    
457            resolver.initializeService();
458    
459            resolver.resolve(cycle, "ContextRootPage");
460    
461            assertEquals("ContextRootPage", resolver.getSimplePageName());
462            assertSame(spec, resolver.getSpecification());
463            assertSame(application, resolver.getNamespace());
464    
465            verify();
466        }
467    
468        public void test_Found_In_Framework()
469        {
470            Log log = newLog();
471            INamespace application = newNamespace();
472    
473            Resource contextRoot = newResource("context/");
474            IComponentSpecification spec = newSpecification();
475            
476            INamespace framework = newNamespace("FrameworkPage", spec);
477            
478            ComponentPropertySource propertySource = newPropertySource(application);
479            
480            trainContainsPage(application, "FrameworkPage", false);
481            
482            ISpecificationSource source = newSource(application, framework);
483            IRequestCycle cycle = newCycle();
484    
485            train(log, ResolverMessages.resolvingPage("FrameworkPage", application));
486    
487            // Pretend the app spec is in the WEB-INF folder
488    
489            trainGetSpecificationLocation(application, contextRoot, "WEB-INF/");
490    
491            train(log, ResolverMessages.checkingResource(contextRoot
492                    .getRelativeResource("WEB-INF/FrameworkPage.page")));
493    
494            trainIsApplicationNamespace(application, true);
495    
496            train(log, ResolverMessages.checkingResource(contextRoot
497                    .getRelativeResource("WEB-INF/myapp/FrameworkPage.page")));
498            train(log, ResolverMessages.checkingResource(contextRoot
499                    .getRelativeResource("WEB-INF/FrameworkPage.page")));
500            train(log, ResolverMessages.checkingResource(contextRoot
501                    .getRelativeResource("FrameworkPage.page")));
502            train(log, ResolverMessages.checkingResource(contextRoot
503                    .getRelativeResource("FrameworkPage.html")));
504    
505            train(log, ResolverMessages.foundFrameworkPage("FrameworkPage"));
506    
507            replay();
508    
509            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
510            resolver.setContextRoot(contextRoot);
511            resolver.setSpecificationSource(source);
512            resolver.setLog(log);
513            resolver.setApplicationId("myapp");
514            resolver.setComponentPropertySource(propertySource);
515    
516            resolver.initializeService();
517    
518            resolver.resolve(cycle, "FrameworkPage");
519    
520            assertEquals("FrameworkPage", resolver.getSimplePageName());
521            assertSame(spec, resolver.getSpecification());
522            assertSame(framework, resolver.getNamespace());
523    
524            verify();
525        }
526    
527        public void test_Found_In_Namespace_Folder()
528        {
529            Log log = newLog();
530    
531            Resource contextRoot = newResource("context/");
532            IComponentSpecification spec = newSpecification();
533    
534            Resource resource = contextRoot.getRelativeResource("WEB-INF/NamespacePage.page");
535    
536            INamespace application = newNamespace();
537    
538            INamespace framework = newNamespace();
539            ISpecificationSource source = newSource(application, framework, resource, spec);
540            IRequestCycle cycle = newCycle();
541    
542            trainContainsPage(application, "NamespacePage", false);
543    
544            train(log, ResolverMessages.resolvingPage("NamespacePage", application));
545    
546            // Pretend the app spec is in the WEB-INF folder
547    
548            trainGetSpecificationLocation(application, contextRoot, "WEB-INF/");
549    
550            train(log, ResolverMessages.checkingResource(resource));
551    
552            train(log, ResolverMessages.installingPage("NamespacePage", application, spec));
553    
554            application.installPageSpecification("NamespacePage", spec);
555    
556            replay();
557    
558            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
559            resolver.setContextRoot(contextRoot);
560            resolver.setSpecificationSource(source);
561            resolver.initializeService();
562            resolver.setLog(log);
563    
564            resolver.resolve(cycle, "NamespacePage");
565    
566            assertEquals("NamespacePage", resolver.getSimplePageName());
567            assertSame(spec, resolver.getSpecification());
568            assertSame(application, resolver.getNamespace());
569    
570            verify();
571        }
572    
573        public void test_Found_In_WebInf_App_Folder()
574        {
575            Log log = newLog();
576    
577            Resource contextRoot = newResource("context/");
578            IComponentSpecification spec = newSpecification();
579    
580            Resource resource = contextRoot.getRelativeResource("WEB-INF/myapp/MyAppPage.page");
581    
582            INamespace application = newNamespace();
583    
584            INamespace framework = newNamespace();
585            ISpecificationSource source = newSource(application, framework, resource, spec);
586            IRequestCycle cycle = newCycle();
587    
588            trainContainsPage(application, "MyAppPage", false);
589    
590            train(log, ResolverMessages.resolvingPage("MyAppPage", application));
591    
592            // Pretend the app spec is in the WEB-INF folder
593    
594            trainGetSpecificationLocation(application, contextRoot, "WEB-INF/");
595    
596            train(log, ResolverMessages.checkingResource(contextRoot
597                    .getRelativeResource("WEB-INF/MyAppPage.page")));
598    
599            trainIsApplicationNamespace(application, true);
600    
601            train(log, ResolverMessages.checkingResource(resource));
602    
603            train(log, ResolverMessages.installingPage("MyAppPage", application, spec));
604    
605            application.installPageSpecification("MyAppPage", spec);
606    
607            replay();
608    
609            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
610            resolver.setContextRoot(contextRoot);
611            resolver.setSpecificationSource(source);
612            resolver.setLog(log);
613            resolver.setApplicationId("myapp");
614    
615            resolver.initializeService();
616    
617            resolver.resolve(cycle, "MyAppPage");
618    
619            assertEquals("MyAppPage", resolver.getSimplePageName());
620            assertSame(spec, resolver.getSpecification());
621            assertSame(application, resolver.getNamespace());
622    
623            verify();
624        }
625    
626        // TODO: Recreate TAPESTRY-1376
627        public void test_Malformed_Found_In_WebInf_App_Folder()
628        {
629            Log log = newLog();
630    
631            Resource contextRoot = newResource("context/");
632            IComponentSpecification spec = newSpecification();
633    
634            Resource resource = contextRoot.getRelativeResource("WEB-INF/myapp/MalformedXmlTag.page");
635    
636            INamespace application = newNamespace();
637    
638            INamespace framework = newNamespace();
639            ISpecificationSource source = newSource(application, framework, resource, spec);
640            IRequestCycle cycle = newCycle();
641    
642            trainContainsPage(application, "MalformedXmlTag", false);
643    
644            train(log, ResolverMessages.resolvingPage("MalformedXmlTag", application));
645    
646            // Pretend the app spec is in the WEB-INF folder
647    
648            trainGetSpecificationLocation(application, contextRoot, "WEB-INF/");
649    
650            train(log, ResolverMessages.checkingResource(contextRoot.getRelativeResource("WEB-INF/MalformedXmlTag.page")));
651    
652            trainIsApplicationNamespace(application, true);
653    
654            train(log, ResolverMessages.checkingResource(resource));
655    
656            train(log, ResolverMessages.installingPage("MalformedXmlTag", application, spec));
657    
658            application.installPageSpecification("MalformedXmlTag", spec);
659    
660            replay();
661    
662            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
663            resolver.setContextRoot(contextRoot);
664            resolver.setSpecificationSource(source);
665            resolver.setLog(log);
666            resolver.setApplicationId("myapp");
667    
668            resolver.initializeService();
669    
670            resolver.resolve(cycle, "MalformedXmlTag");
671    
672            assertEquals("MalformedXmlTag", resolver.getSimplePageName());
673            assertSame(spec, resolver.getSpecification());
674            assertSame(application, resolver.getNamespace());
675    
676            verify();
677        }
678    
679        public void test_Found_In_WebInf_Folder()
680        {
681            Log log = newLog();
682    
683            Resource contextRoot = newResource("context/");
684            IComponentSpecification spec = newSpecification();
685    
686            Resource resource = contextRoot.getRelativeResource("WEB-INF/MyWebInfPage.page");
687    
688            INamespace application = newNamespace();
689    
690            INamespace framework = newNamespace();
691            ISpecificationSource source = newSource(application, framework, resource, spec);
692            IRequestCycle cycle = newCycle();
693    
694            trainContainsPage(application, "MyWebInfPage", false);
695    
696            train(log, ResolverMessages.resolvingPage("MyWebInfPage", application));
697    
698            // Pretend the app spec is in the context root folder
699            // Which isn't really something that happens in a real application
700            // but is necessary to keep from finding the file too early.
701    
702            trainGetSpecificationLocation(application, contextRoot);
703    
704            train(log, ResolverMessages.checkingResource(contextRoot
705                    .getRelativeResource("MyWebInfPage.page")));
706    
707            trainIsApplicationNamespace(application, true);
708    
709            train(log, ResolverMessages.checkingResource(contextRoot
710                    .getRelativeResource("WEB-INF/myapp/MyWebInfPage.page")));
711    
712            train(log, ResolverMessages.checkingResource(resource));
713    
714            train(log, ResolverMessages.installingPage("MyWebInfPage", application, spec));
715    
716            application.installPageSpecification("MyWebInfPage", spec);
717    
718            replay();
719    
720            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
721            resolver.setContextRoot(contextRoot);
722            resolver.setSpecificationSource(source);
723            resolver.setLog(log);
724            resolver.setApplicationId("myapp");
725    
726            resolver.initializeService();
727    
728            resolver.resolve(cycle, "MyWebInfPage");
729    
730            assertEquals("MyWebInfPage", resolver.getSimplePageName());
731            assertSame(spec, resolver.getSpecification());
732            assertSame(application, resolver.getNamespace());
733    
734            verify();
735        }
736    
737        public void test_WebInf()
738        {
739            Log log = newLog();
740            INamespace application = newNamespace();
741            INamespace framework = newNamespace();
742    
743            ISpecificationSource source = newSource(application, framework);
744            IRequestCycle cycle = newCycle();
745            Resource contextRoot = newResource("context/");
746    
747            trainContainsPage(application, "/WEB-Inf/BadName", false);
748    
749            trainIsDebugEnabled(log, false);
750    
751            replay();
752    
753            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
754    
755            resolver.setSpecificationSource(source);
756            resolver.setContextRoot(contextRoot);
757            resolver.setLog(log);
758    
759            resolver.initializeService();
760    
761            try
762            {
763                resolver.resolve(cycle, "/WEB-Inf/BadName");
764                unreachable();
765            }
766            catch (ApplicationRuntimeException ex)
767            {
768                assertEquals(
769                        "Page name '/WEB-Inf/BadName' is not valid, as it directly references a file stored in the WEB-INF folder.",
770                        ex.getMessage());
771            }
772    
773            verify();
774    
775            trainContainsPage(application, "web-inf/BadName", false);
776    
777            trainIsDebugEnabled(log, false);
778    
779            replay();
780    
781            try
782            {
783                resolver.resolve(cycle, "web-inf/BadName");
784                unreachable();
785            }
786            catch (ApplicationRuntimeException ex)
787            {
788                assertEquals(
789                        "Page name 'web-inf/BadName' is not valid, as it directly references a file stored in the WEB-INF folder.",
790                        ex.getMessage());
791            }
792    
793            verify();
794    
795        }
796    
797        public void test_NotFound_Anywhere()
798        {
799            Log log = newLog();
800            INamespace application = newNamespace();
801    
802            Resource contextRoot = newResource("context/");
803    
804            INamespace framework = newNamespace();
805            ISpecificationSource source = newSource(application, framework);
806            IRequestCycle cycle = newCycle();
807    
808            trainContainsPage(application, "MissingPage", false);
809    
810            train(log, ResolverMessages.resolvingPage("MissingPage", application));
811    
812            // Pretend the app spec is in the WEB-INF folder
813    
814            trainGetSpecificationLocation(application, contextRoot, "WEB-INF/");
815    
816            train(log, ResolverMessages.checkingResource(contextRoot
817                    .getRelativeResource("WEB-INF/MissingPage.page")));
818    
819            trainIsApplicationNamespace(application, false);
820    
821            ISpecificationResolverDelegate delegate = newDelegate();
822    
823            trainFindPageSpecification(delegate, cycle, application, "MissingPage", null);
824    
825            trainGetNamespaceId(application, "<application namespace>");
826    
827            replay();
828    
829            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
830            resolver.setContextRoot(contextRoot);
831            resolver.setSpecificationSource(source);
832            resolver.setLog(log);
833            resolver.setApplicationId("myapp");
834            resolver.setDelegate(delegate);
835    
836            resolver.initializeService();
837    
838            try
839            {
840                resolver.resolve(cycle, "MissingPage");
841                unreachable();
842            }
843            catch (PageNotFoundException ex)
844            {
845                assertEquals("Page 'MissingPage' not found in <application namespace>.", ex
846                        .getMessage());
847                assertEquals("MissingPage", ex.getPageName());
848            }
849    
850            verify();
851        }
852    
853        public void test_Provided_By_Delegate()
854        {
855            Log log = newLog();
856            INamespace application = newNamespace();
857    
858            Resource contextRoot = newResource("context/");
859            IComponentSpecification spec = newSpecification();
860    
861            INamespace framework = newNamespace();
862            ISpecificationSource source = newSource(application, framework);
863            IRequestCycle cycle = newCycle();
864    
865            trainContainsPage(application, "DelegatePage", false);
866    
867            train(log, ResolverMessages.resolvingPage("DelegatePage", application));
868    
869            // Pretend the app spec is in the WEB-INF folder
870    
871            trainGetSpecificationLocation(application, contextRoot, "WEB-INF/");
872    
873            train(log, ResolverMessages.checkingResource(contextRoot
874                    .getRelativeResource("WEB-INF/DelegatePage.page")));
875    
876            trainIsApplicationNamespace(application, false);
877    
878            ISpecificationResolverDelegate delegate = newDelegate();
879    
880            trainFindPageSpecification(delegate, cycle, application, "DelegatePage", spec);
881    
882            trainIsDebugEnabled(log, false);
883    
884            application.installPageSpecification("DelegatePage", spec);
885    
886            replay();
887    
888            PageSpecificationResolverImpl resolver = new PageSpecificationResolverImpl();
889            resolver.setContextRoot(contextRoot);
890            resolver.setSpecificationSource(source);
891            resolver.setLog(log);
892            resolver.setApplicationId("myapp");
893            resolver.setDelegate(delegate);
894    
895            resolver.initializeService();
896    
897            resolver.resolve(cycle, "DelegatePage");
898    
899            assertEquals("DelegatePage", resolver.getSimplePageName());
900            assertSame(spec, resolver.getSpecification());
901            assertSame(application, resolver.getNamespace());
902    
903            verify();
904        }
905        
906        private void trainGetPageSpecification(INamespace namespace, String pageName,
907                IComponentSpecification spec)
908        {
909            expect(namespace.getPageSpecification(pageName)).andReturn(spec);
910        }
911    
912        private void trainGetPageSpecification(ISpecificationSource source, Resource resource,
913                IComponentSpecification pageSpec)
914        {
915            expect(source.getPageSpecification(resource)).andReturn(pageSpec);
916        }
917    }