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.BaseComponent;
022    import org.apache.tapestry.INamespace;
023    import org.apache.tapestry.IRequestCycle;
024    import org.apache.tapestry.engine.ISpecificationSource;
025    import org.apache.tapestry.services.ClassFinder;
026    import org.apache.tapestry.spec.IComponentSpecification;
027    import static org.easymock.EasyMock.*;
028    import org.testng.annotations.Test;
029    
030    import java.net.URL;
031    
032    /**
033     * Tests for {@link org.apache.tapestry.resolver.ComponentSpecificationResolverImpl}.
034     * 
035     * @author Howard M. Lewis Ship
036     * @since 4.0
037     */
038    @Test
039    public class TestComponentSpecificationResolver extends AbstractSpecificationResolverTestCase
040    {
041        private void trainIsDeprecated(IComponentSpecification spec,
042                boolean isDeprecated)
043        {
044            expect(spec.isDeprecated()).andReturn(isDeprecated);
045        }
046    
047        protected ISpecificationSource newSource(Resource resource, IComponentSpecification spec)
048        {
049            ISpecificationSource source = newMock(ISpecificationSource.class);
050    
051            expect(source.getComponentSpecification(resource)).andReturn(spec);
052    
053            return source;
054        }
055    
056        protected ISpecificationSource newSource(INamespace framework)
057        {
058            ISpecificationSource source = newMock(ISpecificationSource.class);
059    
060            expect(source.getFrameworkNamespace()).andReturn(framework);
061    
062            return source;
063        }
064    
065        private ISpecificationResolverDelegate newDelegate(IRequestCycle cycle, INamespace namespace,
066                String type, IComponentSpecification spec)
067        {
068            ISpecificationResolverDelegate delegate = newMock(ISpecificationResolverDelegate.class);
069            checkOrder(delegate, false);
070            
071            expect(delegate.findComponentSpecification(cycle, namespace, type)).andReturn(spec).anyTimes();
072    
073            return delegate;
074        }
075        
076        public void test_Not_Found_In_Any_Namespace()
077        {
078            IRequestCycle cycle = newCycle();
079            Location l = newLocation();
080            
081            INamespace namespace = newMock(INamespace.class);
082            
083            ApplicationRuntimeException exception = new ApplicationRuntimeException("");
084    
085            expect(namespace.getChildNamespace("invalid")).andThrow(exception);
086            
087            replay();
088    
089            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
090    
091            try
092            {
093                resolver.resolve(cycle, namespace, "invalid:MyComponent", l);
094                unreachable();
095            }
096            catch (ApplicationRuntimeException ex)
097            {
098                assertSame(ex.getCause(), exception);
099            }
100    
101            verify();
102        }    
103    
104        public void test_Found_In_Namespace()
105        {
106            IRequestCycle cycle = newCycle();
107            Location l = newLocation();
108            
109            IComponentSpecification spec = newSpec();
110            INamespace namespace = newMock(INamespace.class);
111    
112            expect(namespace.containsComponentType("MyComponent")).andReturn(true);
113    
114            expect(namespace.getComponentSpecification("MyComponent")).andReturn(spec);
115    
116            trainIsDeprecated(spec, false);
117            
118            replay();
119    
120            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
121    
122            resolver.resolve(cycle, namespace, "MyComponent", l);
123    
124            assertSame(spec, resolver.getSpecification());
125            assertSame(namespace, resolver.getNamespace());
126    
127            verify();
128        }
129    
130        public void test_Deprecated()
131        {
132            IRequestCycle cycle = newCycle();
133            Location l = newLocation();
134            
135            IComponentSpecification spec = newSpec();
136            INamespace namespace = newMock(INamespace.class);
137            
138            expect(namespace.containsComponentType("MyComponent")).andReturn(true);
139            
140            expect(namespace.getComponentSpecification("MyComponent")).andReturn(spec);
141            
142            trainIsDeprecated(spec, true);
143    
144            Log log = newMock(Log.class);
145            
146            log.warn(startsWith("Component 'MyComponent' ("));
147            // at classpath:/org/apache/tapestry/resolver/TestComponentSpecificationResolver, line 1) is deprecated, and will likely
148            // be removed in a later release. Consult its documentation to find a replacement component.");
149            
150            replay();
151            
152            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
153            resolver.setLog(log);
154            
155            resolver.resolve(cycle, namespace, "MyComponent", l);
156            
157            assertSame(spec, resolver.getSpecification());
158            assertSame(namespace, resolver.getNamespace());
159    
160            verify();
161        }
162    
163        public void test_Found_In_Child_Namespace()
164        {
165            IRequestCycle cycle = newCycle();
166            Location l = newLocation();
167    
168            IComponentSpecification spec = newSpec();
169            INamespace namespace = newMock(INamespace.class);
170            INamespace library = newMock(INamespace.class);
171    
172            expect(namespace.getChildNamespace("lib")).andReturn(library);
173    
174            expect(library.containsComponentType("MyComponent")).andReturn(true);
175            
176            expect(library.getComponentSpecification("MyComponent")).andReturn(spec);
177    
178            trainIsDeprecated(spec, false);
179    
180            replay();
181    
182            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
183    
184            resolver.resolve(cycle, namespace, "lib:MyComponent", l);
185    
186            assertSame(spec, resolver.getSpecification());
187            assertSame(library, resolver.getNamespace());
188    
189            verify();
190        }
191    
192        public void test_Search_Found_Relative()
193        {
194            IRequestCycle cycle = newCycle();
195            Location l = newLocation();
196    
197            IComponentSpecification spec = newSpec();
198            INamespace namespace = newMock(INamespace.class);
199            
200            Log log = newMock(Log.class);
201    
202            Resource namespaceLocation = newResource("LibraryStandin.library");
203            Resource specLocation = namespaceLocation.getRelativeResource("MyComponent.jwc");
204    
205            expect(namespace.containsComponentType("MyComponent")).andReturn(false);
206    
207            train(log, ResolverMessages.resolvingComponent("MyComponent", namespace));
208    
209            expect(namespace.getSpecificationLocation()).andReturn(namespaceLocation);
210    
211            train(log, ResolverMessages.checkingResource(specLocation));
212            
213            ISpecificationSource source = newSource(specLocation, spec);
214            
215            train(log, ResolverMessages.installingComponent("MyComponent", namespace, spec));
216    
217            namespace.installComponentSpecification("MyComponent", spec);
218    
219            trainIsDeprecated(spec, false);
220    
221            replay();
222    
223            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
224            resolver.setLog(log);
225            resolver.setSpecificationSource(source);
226    
227            resolver.resolve(cycle, namespace, "MyComponent", l);
228    
229            assertSame(spec, resolver.getSpecification());
230            assertSame(namespace, resolver.getNamespace());
231    
232            verify();
233        }
234    
235        public void test_Found_In_Framework_Namespace()
236        {
237            IRequestCycle cycle = newCycle();
238            Location l = newLocation();
239    
240            IComponentSpecification spec = newSpec();
241            INamespace namespace = newMock(INamespace.class);
242            ISpecificationResolverDelegate delegate = newMock(ISpecificationResolverDelegate.class);
243            
244            Log log = newMock(Log.class);
245            INamespace framework = newMock(INamespace.class);
246    
247            Resource namespaceLocation = newResource("LibraryStandin.library");
248    
249            expect(namespace.containsComponentType("FrameworkComponent")).andReturn(false);
250    
251            train(log, ResolverMessages.resolvingComponent("FrameworkComponent", namespace));
252    
253            expect(namespace.getSpecificationLocation()).andReturn(namespaceLocation);
254    
255            train(log, ResolverMessages.checkingResource(namespaceLocation
256                    .getRelativeResource("FrameworkComponent.jwc")));
257            
258            expect(namespace.isApplicationNamespace()).andReturn(false);
259            
260            expect(delegate.findComponentSpecification(cycle, namespace, "FrameworkComponent")).andReturn(null);
261            
262            trainGetPackages(namespace, "org.foo");
263            
264            ClassFinder finder = newClassFinder("org.foo", "FrameworkComponent", null);
265            
266            ISpecificationSource source = newSource(framework);
267    
268            expect(framework.containsComponentType("FrameworkComponent")).andReturn(true);
269    
270            expect(framework.getComponentSpecification("FrameworkComponent")).andReturn(spec);
271            
272            train(log, ResolverMessages
273                    .installingComponent("FrameworkComponent", namespace, spec));
274            namespace.installComponentSpecification("FrameworkComponent", spec);
275    
276            trainIsDeprecated(spec, false);
277    
278            replay();
279    
280            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
281            resolver.setLog(log);
282            resolver.setSpecificationSource(source);
283            resolver.setClassFinder(finder);
284            resolver.setDelegate(delegate);
285            
286            resolver.resolve(cycle, namespace, "FrameworkComponent", l);
287    
288            assertSame(spec, resolver.getSpecification());
289            assertSame(namespace, resolver.getNamespace());
290    
291            verify();
292        }
293    
294        public void test_Provided_By_Delegate()
295        {
296            IRequestCycle cycle = newCycle();
297            Location l = newLocation();
298    
299            IComponentSpecification spec = newSpec();
300            INamespace namespace = newMock(INamespace.class);
301            
302            Log log = newMock(Log.class);
303            //INamespace framework = newMock(INamespace.class);
304            
305            ISpecificationResolverDelegate delegate = newDelegate(
306                    cycle,
307                    namespace,
308                    "DelegateComponent",
309                    spec);
310            
311            expect(namespace.containsComponentType("DelegateComponent")).andReturn(false);
312    
313            train(log, ResolverMessages.resolvingComponent("DelegateComponent", namespace));
314    
315            Resource namespaceLocation = newResource("LibraryStandin.library");
316            
317            expect(namespace.getSpecificationLocation()).andReturn(namespaceLocation);
318    
319            train(log, ResolverMessages.checkingResource(namespaceLocation
320                    .getRelativeResource("DelegateComponent.jwc")));
321    
322            expect(namespace.isApplicationNamespace()).andReturn(false);
323            
324            expect(log.isDebugEnabled()).andReturn(false);
325            
326            namespace.installComponentSpecification("DelegateComponent", spec);
327            
328            trainIsDeprecated(spec, false);
329            
330            replay();
331    
332            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
333            resolver.setLog(log);
334            resolver.setDelegate(delegate);
335            
336            resolver.resolve(cycle, namespace, "DelegateComponent", l);
337            
338            assertSame(spec, resolver.getSpecification());
339            assertSame(namespace, resolver.getNamespace());
340            
341            verify();
342        }
343    
344        private void trainGetPackages(INamespace namespace, String packages)
345        {
346            expect(namespace.getPropertyValue("org.apache.tapestry.component-class-packages"))
347            .andReturn(packages);
348        }
349    
350        private ClassFinder newClassFinder(String packages, String className, Class result)
351        {
352            ClassFinder finder = newMock(ClassFinder.class);
353    
354            expect(finder.findClass(packages, className)).andReturn(result);
355    
356            return finder;
357        }
358    
359        public void test_Not_Found()
360        {
361            IRequestCycle cycle = newCycle();
362            Location l = newLocation();
363            
364            Log log = newMock(Log.class);
365            
366            INamespace namespace = newMock(INamespace.class);
367            INamespace framework = newMock(INamespace.class);
368            
369            ISpecificationResolverDelegate delegate = newDelegate(
370                    cycle,
371                    namespace,
372                    "NotFoundComponent",
373                    null);
374            
375            Resource namespaceLocation = newResource("LibraryStandin.library");
376            
377            expect(namespace.containsComponentType("NotFoundComponent")).andReturn(false);
378    
379            train(log, ResolverMessages.resolvingComponent("NotFoundComponent", namespace));
380    
381            expect(namespace.getSpecificationLocation()).andReturn(namespaceLocation);
382    
383            train(log, ResolverMessages.checkingResource(namespaceLocation
384                    .getRelativeResource("NotFoundComponent.jwc")));
385    
386            expect(namespace.isApplicationNamespace()).andReturn(false);
387    
388            ISpecificationSource source = newSource(framework);
389    
390            expect(framework.containsComponentType("NotFoundComponent")).andReturn(false);
391    
392            ClassFinder finder = newClassFinder("org.foo", "NotFoundComponent", null);
393            trainGetPackages(namespace, "org.foo");
394    
395            replay();
396    
397            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
398            resolver.setLog(log);
399            resolver.setSpecificationSource(source);
400            resolver.setDelegate(delegate);
401            resolver.setClassFinder(finder);
402    
403            try
404            {
405                resolver.resolve(cycle, namespace, "NotFoundComponent", l);
406                unreachable();
407            }
408            catch (ApplicationRuntimeException ex)
409            {
410                assertEquals(
411                        "Component 'NotFoundComponent' not found in EasyMock for interface org.apache.tapestry.INamespace.",
412                        ex.getMessage());
413                assertSame(l, ex.getLocation());
414            }
415    
416            verify();
417        }
418    
419        /**
420         * Test for checking inside the WEB-INF/app folder (app is the application id, i.e., the servlet
421         * name).
422         */
423    
424        public void test_Found_In_App_Folder()
425        {
426            IRequestCycle cycle = newCycle();
427            Location l = newLocation();
428            
429            IComponentSpecification spec = newSpec();
430            Log log = newLog();
431    
432            Resource contextRoot = newResource("context/");
433            
434            INamespace namespace = newMock(INamespace.class);
435            
436            Resource namespaceLocation = newResource("LibraryStandin.library");
437            Resource specLocation = contextRoot.getRelativeResource("WEB-INF/myapp/MyAppComponent.jwc");
438            
439            expect(namespace.containsComponentType("MyAppComponent")).andReturn(false);
440    
441            train(log, ResolverMessages.resolvingComponent("MyAppComponent", namespace));
442    
443            expect(namespace.getSpecificationLocation()).andReturn(namespaceLocation);
444    
445            train(log, ResolverMessages.checkingResource(namespaceLocation
446                    .getRelativeResource("MyAppComponent.jwc")));
447            
448            expect(namespace.isApplicationNamespace()).andReturn(true);
449    
450            train(log, ResolverMessages.checkingResource(specLocation));
451            
452            ISpecificationSource source = newSource(specLocation, spec);
453            
454            train(log, ResolverMessages.installingComponent("MyAppComponent", namespace, spec));
455            
456            namespace.installComponentSpecification("MyAppComponent", spec);
457    
458            trainIsDeprecated(spec, false);
459    
460            replay();
461    
462            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
463            resolver.setLog(log);
464            resolver.setSpecificationSource(source);
465            resolver.setContextRoot(contextRoot);
466            resolver.setApplicationId("myapp");
467            resolver.initializeService();
468    
469            resolver.resolve(cycle, namespace, "MyAppComponent", l);
470    
471            assertSame(spec, resolver.getSpecification());
472            assertSame(namespace, resolver.getNamespace());
473    
474            verify();
475        }
476    
477        public void test_Found_In_Web_Inf_Folder()
478        {
479            IRequestCycle cycle = newCycle();
480            Location l = newLocation();
481    
482            IComponentSpecification spec = newSpec();
483            Log log = newLog();
484    
485            Resource contextRoot = newResource("context/");
486    
487            INamespace namespace = newMock(INamespace.class);
488    
489            Resource namespaceLocation = newResource("LibraryStandin.library");
490            Resource specLocation = contextRoot.getRelativeResource("WEB-INF/MyWebInfComponent.jwc");
491            
492            expect(namespace.containsComponentType("MyWebInfComponent")).andReturn(false);
493            
494            train(log, ResolverMessages.resolvingComponent("MyWebInfComponent", namespace));
495    
496            expect(namespace.getSpecificationLocation()).andReturn(namespaceLocation);
497    
498            train(log, ResolverMessages.checkingResource(namespaceLocation
499                    .getRelativeResource("MyWebInfComponent.jwc")));
500    
501            expect(namespace.isApplicationNamespace()).andReturn(true);
502    
503            train(log, ResolverMessages.checkingResource(contextRoot
504                    .getRelativeResource("WEB-INF/myapp/MyWebInfComponent.jwc")));
505            train(log, ResolverMessages.checkingResource(specLocation));
506            
507            ISpecificationSource source = newSource(specLocation, spec);
508            
509            train(log, ResolverMessages.installingComponent("MyWebInfComponent", namespace, spec));
510    
511            namespace.installComponentSpecification("MyWebInfComponent", spec);
512            
513            trainIsDeprecated(spec, false);
514            
515            replay();
516    
517            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
518            resolver.setLog(log);
519            resolver.setSpecificationSource(source);
520            resolver.setContextRoot(contextRoot);
521            resolver.setApplicationId("myapp");
522            resolver.initializeService();
523    
524            resolver.resolve(cycle, namespace, "MyWebInfComponent", l);
525    
526            assertSame(spec, resolver.getSpecification());
527            assertSame(namespace, resolver.getNamespace());
528    
529            verify();
530        }
531    
532        public void test_Found_In_Context_Root()
533        {
534            IRequestCycle cycle = newCycle();
535            Location l = newLocation();
536    
537            IComponentSpecification spec = newSpec();
538            Log log = newLog();
539    
540            Resource contextRoot = newResource("context/");
541            
542            INamespace namespace = newMock(INamespace.class);
543            
544            Resource namespaceLocation = newResource("LibraryStandin.library");
545            Resource specLocation = contextRoot.getRelativeResource("ContextRootComponent.jwc");
546            
547            
548    
549            expect(namespace.containsComponentType("ContextRootComponent")).andReturn(false);
550    
551            train(log, ResolverMessages.resolvingComponent("ContextRootComponent", namespace));
552            
553            expect(namespace.getSpecificationLocation()).andReturn(namespaceLocation);
554    
555            train(log, ResolverMessages.checkingResource(namespaceLocation
556                    .getRelativeResource("ContextRootComponent.jwc")));
557            
558            expect(namespace.isApplicationNamespace()).andReturn(true);
559    
560            train(log, ResolverMessages.checkingResource(contextRoot
561                    .getRelativeResource("WEB-INF/myapp/ContextRootComponent.jwc")));
562            train(log, ResolverMessages.checkingResource(contextRoot
563                    .getRelativeResource("WEB-INF/ContextRootComponent.jwc")));
564            
565            train(log, ResolverMessages.checkingResource(specLocation));
566            
567            ISpecificationSource source = newSource(specLocation, spec);
568            
569            train(log, ResolverMessages.installingComponent(
570                    "ContextRootComponent",
571                    namespace,
572                    spec));
573    
574            namespace.installComponentSpecification("ContextRootComponent", spec);
575    
576            trainIsDeprecated(spec, false);
577            
578            replay();
579    
580            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
581            resolver.setLog(log);
582            resolver.setSpecificationSource(source);
583            resolver.setContextRoot(contextRoot);
584            resolver.setApplicationId("myapp");
585            resolver.initializeService();
586    
587            resolver.resolve(cycle, namespace, "ContextRootComponent", l);
588    
589            assertSame(spec, resolver.getSpecification());
590            assertSame(namespace, resolver.getNamespace());
591    
592            verify();
593        }
594    
595        public void test_Found_Component_Class()
596        {   
597            INamespace namespace = newMock(INamespace.class);
598    
599            trainGetPackages(namespace, "org.foo");
600            ClassFinder finder = newClassFinder("org.foo", "folder.MyComponent", BaseComponent.class);
601    
602            Resource componentResource = newResource();
603            Resource namespaceResource = newResource("folder/MyComponent.jwc", componentResource);
604            
605            trainGetResource(namespace, namespaceResource);
606    
607            URL componentUrl = this.getClass().getResource("MyComponent.jwc");
608            expect(componentResource.getResourceURL()).andReturn(componentUrl);
609    
610            replay();
611    
612            ComponentSpecificationResolverImpl resolver = new ComponentSpecificationResolverImpl();
613            resolver.setClassFinder(finder);
614    
615            IComponentSpecification spec = resolver.searchForComponentClass(namespace, "folder/MyComponent");
616    
617            assertEquals(BaseComponent.class.getName(), spec.getComponentClassName());
618            assertSame(componentResource, spec.getSpecificationLocation());
619            assertSame(componentResource, spec.getLocation().getResource());
620    
621            verify();
622        }
623    
624        private void trainGetResource(INamespace namespace, Resource resource)
625        {
626            expect(namespace.getSpecificationLocation()).andReturn(resource);
627        }
628    
629        private Resource newResource(String relativePath, Resource relativeResource)
630        {
631            Resource resource = newMock(Resource.class);
632            checkOrder(resource, false);
633            
634            expect(resource.getRelativeResource(relativePath)).andReturn(relativeResource);
635    
636            return resource;
637        }
638    }