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.enhance;
016    
017    import org.apache.hivemind.ApplicationRuntimeException;
018    import org.apache.hivemind.Location;
019    import org.apache.hivemind.service.MethodSignature;
020    import org.apache.tapestry.BaseComponentTestCase;
021    import org.apache.tapestry.engine.HomeService;
022    import org.apache.tapestry.engine.IEngineService;
023    import org.apache.tapestry.services.InjectedValueProvider;
024    import org.apache.tapestry.spec.InjectSpecification;
025    import org.apache.tapestry.spec.InjectSpecificationImpl;
026    import static org.easymock.EasyMock.expect;
027    import org.testng.annotations.Test;
028    
029    import java.lang.reflect.Modifier;
030    import java.util.HashMap;
031    import java.util.Map;
032    
033    /**
034     * Tests for {@link org.apache.tapestry.enhance.InjectObjectWorker}.
035     * 
036     * @author Howard M. Lewis Ship
037     * @since 4.0
038     */
039    @Test
040    public class TestInjectObjectWorker extends BaseComponentTestCase
041    {
042        private InjectSpecification newSpec(String name, String locator, Location location)
043        {
044            InjectSpecification is = new InjectSpecificationImpl();
045    
046            is.setProperty(name);
047            is.setObject(locator);
048            is.setLocation(location);
049    
050            return is;
051        }
052    
053        public void testNoExistingProperty()
054        {
055            Location l = newLocation();
056            Object injectedValue = new Object();
057    
058            InjectSpecification spec = newSpec("fred", "service:barney", l);
059    
060            EnhancementOperation op = newMock(EnhancementOperation.class);
061    
062            InjectedValueProvider p = newMock(InjectedValueProvider.class);
063    
064            expect(op.getPropertyType("fred")).andReturn(null);
065    
066            op.claimReadonlyProperty("fred");
067    
068            expect(p.obtainValue("service:barney", l)).andReturn(injectedValue);
069    
070            // When the same bean is injected multiple times, the field name
071            // returned won't match the field name suggested; make sure the code
072            // generation used the correct field name.
073    
074            expect(op.addInjectedField("_$fred", Object.class, injectedValue)).andReturn("_$gnarly");
075    
076            op.addMethod(
077                    Modifier.PUBLIC,
078                    new MethodSignature(Object.class, "getFred", null, null),
079                    "return _$gnarly;",
080                    l);
081    
082            replay();
083    
084            InjectObjectWorker w = new InjectObjectWorker();
085            w.setProvider(p);
086    
087            w.performEnhancement(op, spec);
088    
089            verify();
090        }
091    
092        public void testWithExistingProperty()
093        {
094            Location l = newLocation();
095            Object injectedValue = new HomeService();
096    
097            InjectSpecification spec = newSpec("wilma", "service:betty", l);
098    
099            EnhancementOperation op = newMock(EnhancementOperation.class);
100    
101            InjectedValueProvider p = newMock(InjectedValueProvider.class);
102    
103            expect(op.getPropertyType("wilma")).andReturn(IEngineService.class);
104    
105            op.claimReadonlyProperty("wilma");
106    
107            expect(p.obtainValue("service:betty", l)).andReturn(injectedValue);
108    
109            expect(op.addInjectedField("_$wilma", IEngineService.class, injectedValue)).andReturn("_$wilma");
110    
111            op.addMethod(Modifier.PUBLIC, new MethodSignature(IEngineService.class, "getWilma", null,
112                    null), "return _$wilma;", l);
113    
114            replay();
115    
116            InjectObjectWorker w = new InjectObjectWorker();
117            w.setProvider(p);
118    
119            w.performEnhancement(op, spec);
120    
121            verify();
122        }
123    
124        /**
125         * Test what happens when the value to be injected is null (usually indicating an error in the
126         * locator and/or a configuration error inside the HiveMind descriptors).
127         */
128    
129        public void testInjectNull()
130        {
131            Location l = newLocation();
132    
133            InjectSpecification spec = newSpec("fred", "service:barney", l);
134    
135            EnhancementOperation op = newMock(EnhancementOperation.class);
136    
137            InjectedValueProvider p = newMock(InjectedValueProvider.class);
138    
139            expect(op.getPropertyType("fred")).andReturn(null);
140    
141            op.claimReadonlyProperty("fred");
142    
143            expect(p.obtainValue("service:barney", l)).andReturn(null);
144    
145            replay();
146    
147            InjectObjectWorker w = new InjectObjectWorker();
148            w.setProvider(p);
149    
150            try
151            {
152                w.performEnhancement(op, spec);
153                unreachable();
154            }
155            catch (ApplicationRuntimeException ex)
156            {
157                assertEquals("Value obtained using locator 'service:barney' is null.", ex.getMessage());
158                assertSame(l, ex.getLocation());
159            }
160    
161            verify();
162        }
163    
164        public void testInjectedValueWrongType()
165        {
166            Location l = newLocation();
167    
168            InjectSpecification spec = newSpec("fred", "service:barney", l);
169    
170            EnhancementOperation op = newMock(EnhancementOperation.class);
171    
172            InjectedValueProvider p = newMock(InjectedValueProvider.class);
173    
174            expect(op.getPropertyType("fred")).andReturn(IEngineService.class);
175    
176            op.claimReadonlyProperty("fred");
177    
178            expect(p.obtainValue("service:barney", l)).andReturn("INJECTED-VALUE");
179    
180            replay();
181    
182            InjectObjectWorker w = new InjectObjectWorker();
183            w.setProvider(p);
184    
185            try
186            {
187                w.performEnhancement(op, spec);
188                unreachable();
189    
190            }
191            catch (ApplicationRuntimeException ex)
192            {
193                assertEquals(
194                        "The value obtained using locator 'service:barney' (INJECTED-VALUE) is not compatible with the existing property (of type org.apache.tapestry.engine.IEngineService).",
195                        ex.getMessage());
196                assertSame(l, ex.getLocation());
197            }
198    
199            verify();
200        }
201        
202        public void testInjectMap()
203        {
204            Location l = newLocation();
205            Map injectedValue = new HashMap();
206            
207            InjectSpecification spec = newSpec("fred", "service:barney", l);
208            
209            EnhancementOperation op = newMock(EnhancementOperation.class);
210            
211            InjectedValueProvider p = newMock(InjectedValueProvider.class);
212            
213            expect(op.getPropertyType("fred")).andReturn(Map.class);
214            
215            op.claimReadonlyProperty("fred");
216            
217            expect(p.obtainValue("service:barney", l)).andReturn(new HashMap());
218            
219            expect(op.addInjectedField("_$fred", Map.class, injectedValue)).andReturn("_$fred");
220            
221            op.addMethod(Modifier.PUBLIC, new MethodSignature(Map.class, "getFred", null,
222                    null), "return _$fred;", l);
223            
224            replay();
225            
226            InjectObjectWorker w = new InjectObjectWorker();
227            w.setProvider(p);
228            
229            w.performEnhancement(op, spec);
230    
231            verify();
232        }
233    }