001    // Copyright 2006, 2007, 2008, 2010, 2011 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.tapestry5.ioc.test;
016    
017    import static java.lang.Thread.sleep;
018    import static org.easymock.EasyMock.isA;
019    
020    import java.io.File;
021    import java.lang.annotation.Annotation;
022    import java.lang.reflect.Method;
023    import java.net.URL;
024    import java.util.Locale;
025    
026    import org.apache.tapestry5.ioc.*;
027    import org.apache.tapestry5.ioc.annotations.IntermediateType;
028    import org.apache.tapestry5.ioc.def.*;
029    import org.apache.tapestry5.ioc.services.ClassPropertyAdapter;
030    import org.apache.tapestry5.ioc.services.MasterObjectProvider;
031    import org.apache.tapestry5.ioc.services.PerthreadManager;
032    import org.apache.tapestry5.ioc.services.PropertyAccess;
033    import org.apache.tapestry5.ioc.services.PropertyAdapter;
034    import org.apache.tapestry5.ioc.services.SymbolSource;
035    import org.apache.tapestry5.ioc.services.ThreadLocale;
036    import org.apache.tapestry5.ioc.services.TypeCoercer;
037    import org.slf4j.Logger;
038    
039    /**
040     * Add factory and trainer methods for the public interfaces of Tapestry IOC.
041     */
042    public class IOCTestCase extends TestBase
043    {
044    
045        /**
046         * Builds a Registry for the provided modules; caller should shutdown the Registry when done.
047         */
048        protected final Registry buildRegistry(Class... moduleClasses)
049        {
050            RegistryBuilder builder = new RegistryBuilder();
051    
052            builder.add(moduleClasses);
053    
054            return builder.build();
055        }
056    
057        protected final Method findMethod(Class clazz, String methodName)
058        {
059            for (Method method : clazz.getMethods())
060            {
061                if (method.getName().equals(methodName))
062                    return method;
063            }
064    
065            throw new IllegalArgumentException(String.format("Class %s does not provide a method named '%s'.",
066                    clazz.getName(), methodName));
067        }
068    
069        protected final Method findMethod(Object subject, String methodName)
070        {
071            return findMethod(subject.getClass(), methodName);
072        }
073    
074        protected final Method findMethod(String methodName)
075        {
076            return findMethod(this, methodName);
077        }
078    
079        /**
080         * Combines a series of lines by forming a string with a line separator after each line.
081         */
082        protected final String join(String... lines)
083        {
084            StringBuilder result = new StringBuilder();
085    
086            for (String line : lines)
087            {
088                result.append(line);
089                result.append("\n");
090            }
091    
092            return result.toString();
093        }
094    
095        protected final AnnotationProvider mockAnnotationProvider()
096        {
097            return newMock(AnnotationProvider.class);
098        }
099    
100        @SuppressWarnings("unchecked")
101        protected final <T> Configuration<T> mockConfiguration()
102        {
103            return newMock(Configuration.class);
104        }
105    
106        protected final ContributionDef mockContributionDef()
107        {
108            return newMock(ContributionDef.class);
109        }
110    
111        protected final DecoratorDef mockDecoratorDef()
112        {
113            return newMock(DecoratorDef.class);
114        }
115    
116        protected final DecoratorDef2 mockDecoratorDef2()
117        {
118            return newMock(DecoratorDef2.class);
119        }
120    
121        protected final AdvisorDef mockAdvisorDef()
122        {
123            return newMock(AdvisorDef.class);
124        }
125    
126        protected final AdvisorDef2 mockAdvisorDef2()
127        {
128            return newMock(AdvisorDef2.class);
129        }
130    
131        protected final Location mockLocation()
132        {
133            return newMock(Location.class);
134        }
135    
136        protected final Logger mockLogger()
137        {
138            return newMock(Logger.class);
139        }
140    
141        protected final void stub_isDebugEnabled(Logger logger, boolean enabled)
142        {
143            expect(logger.isDebugEnabled()).andStubReturn(enabled);
144        }
145    
146        @SuppressWarnings("unchecked")
147        protected final <K, V> MappedConfiguration<K, V> mockMappedConfiguration()
148        {
149            return newMock(MappedConfiguration.class);
150        }
151    
152        protected final MessageFormatter mockMessageFormatter()
153        {
154            return newMock(MessageFormatter.class);
155        }
156    
157        protected final Messages mockMessages()
158        {
159            return newMock(Messages.class);
160        }
161    
162        protected final ModuleDef mockModuleDef()
163        {
164            return newMock(ModuleDef.class);
165        }
166    
167        protected final ModuleDef2 mockModuleDef2()
168        {
169            return newMock(ModuleDef2.class);
170        }
171    
172        protected final ObjectCreator mockObjectCreator()
173        {
174            return newMock(ObjectCreator.class);
175        }
176    
177        protected final ObjectProvider mockObjectProvider()
178        {
179            return newMock(ObjectProvider.class);
180        }
181    
182        @SuppressWarnings("unchecked")
183        protected final <T> OrderedConfiguration<T> mockOrderedConfiguration()
184        {
185            return newMock(OrderedConfiguration.class);
186        }
187    
188        protected final Resource mockResource()
189        {
190            return newMock(Resource.class);
191        }
192    
193        /**
194         * Frequently used as a placeholder for an arbitrary service (but its nice and simple).
195         */
196        protected final Runnable mockRunnable()
197        {
198            return newMock(Runnable.class);
199        }
200    
201        protected final ServiceBuilderResources mockServiceBuilderResources()
202        {
203            return newMock(ServiceBuilderResources.class);
204        }
205    
206        protected final ServiceDecorator mockServiceDecorator()
207        {
208            return newMock(ServiceDecorator.class);
209        }
210    
211        protected final ServiceDef mockServiceDef()
212        {
213            return newMock(ServiceDef.class);
214        }
215    
216        protected final ObjectLocator mockObjectLocator()
217        {
218            return newMock(ObjectLocator.class);
219        }
220    
221        protected final ServiceResources mockServiceResources()
222        {
223            return newMock(ServiceResources.class);
224        }
225    
226        protected final SymbolSource mockSymbolSource()
227        {
228            return newMock(SymbolSource.class);
229        }
230    
231        protected final ThreadLocale mockThreadLocale()
232        {
233            return newMock(ThreadLocale.class);
234        }
235    
236        protected final TypeCoercer mockTypeCoercer()
237        {
238            return newMock(TypeCoercer.class);
239        }
240    
241        protected final void stub_contains(Messages messages, boolean contained)
242        {
243            expect(messages.contains(isA(String.class))).andStubReturn(contained);
244        }
245    
246        protected <S, T> void train_coerce(TypeCoercer coercer, S input, Class<T> expectedType, T coercedValue)
247        {
248            expect(coercer.coerce(input, expectedType)).andReturn(coercedValue);
249        }
250    
251        protected final void train_contains(Messages messages, String key, boolean result)
252        {
253            expect(messages.contains(key)).andReturn(result).atLeastOnce();
254        }
255    
256        protected final void train_createInterceptor(ServiceDecorator decorator, Object coreObject, Object interceptor)
257        {
258            expect(decorator.createInterceptor(coreObject)).andReturn(interceptor);
259        }
260    
261        protected final void train_createObject(ObjectCreator creator, Object service)
262        {
263            expect(creator.createObject()).andReturn(service);
264        }
265    
266        protected final void train_expandSymbols(SymbolSource source, String input)
267        {
268            train_expandSymbols(source, input, input);
269        }
270    
271        protected final void train_expandSymbols(SymbolSource source, String input, String expanded)
272        {
273            expect(source.expandSymbols(input)).andReturn(expanded);
274        }
275    
276        protected final void train_forFile(Resource resource, String relativePath, Resource file)
277        {
278            expect(resource.forFile(relativePath)).andReturn(file);
279        }
280    
281        protected final void train_forLocale(Resource base, Locale locale, Resource resource)
282        {
283            expect(base.forLocale(locale)).andReturn(resource);
284        }
285    
286        /**
287         * Have to put the result before the varargs.
288         */
289        protected void train_format(MessageFormatter formatter, String result, Object... arguments)
290        {
291            expect(formatter.format(arguments)).andReturn(result);
292        }
293    
294        protected final void train_get(Messages messages, String key, String message)
295        {
296            expect(messages.get(key)).andReturn(message).atLeastOnce();
297        }
298    
299        protected final void train_getLocale(ThreadLocale threadLocale, Locale locale)
300        {
301            expect(threadLocale.getLocale()).andReturn(locale);
302        }
303    
304        protected final void train_getLogger(LoggerSource source, String serviceId, Logger logger)
305        {
306            expect(source.getLogger(serviceId)).andReturn(logger).atLeastOnce();
307        }
308    
309        protected final void train_getMessageFormatter(Messages messages, String key, MessageFormatter formatter)
310        {
311            expect(messages.getFormatter(key)).andReturn(formatter).atLeastOnce();
312        }
313    
314        protected final void train_getPath(Resource r, String path)
315        {
316            expect(r.getPath()).andReturn(path).atLeastOnce();
317        }
318    
319        protected final <T> void train_getService(ObjectLocator locator, Class<T> serviceInterface, T service)
320        {
321            expect(locator.getService(serviceInterface)).andReturn(service);
322        }
323    
324        protected final <T> void train_getService(ObjectLocator locator, String serviceId, Class<T> serviceInterface,
325                T service)
326        {
327            expect(locator.getService(serviceId, serviceInterface)).andReturn(service);
328        }
329    
330        protected final void train_getServiceId(ServiceDef def, String serviceId)
331        {
332            expect(def.getServiceId()).andReturn(serviceId).atLeastOnce();
333        }
334    
335        protected final void train_getServiceId(ServiceResources resources, String serviceId)
336        {
337            expect(resources.getServiceId()).andReturn(serviceId).atLeastOnce();
338        }
339    
340        protected final void train_getServiceInterface(ServiceDef def, Class serviceInterface)
341        {
342            expect(def.getServiceInterface()).andReturn(serviceInterface).atLeastOnce();
343        }
344    
345        protected final void train_getServiceInterface(ServiceResources resources, Class serviceInterface)
346        {
347            expect(resources.getServiceInterface()).andReturn(serviceInterface).atLeastOnce();
348        }
349    
350        protected final void train_getLogger(ServiceResources resources, Logger log)
351        {
352            expect(resources.getLogger()).andReturn(log).atLeastOnce();
353        }
354    
355        protected final void train_isDebugEnabled(Logger log, boolean debugEnabled)
356        {
357            expect(log.isDebugEnabled()).andReturn(debugEnabled);
358        }
359    
360        protected final void train_isTraceEnabled(Logger log, boolean traceEnabled)
361        {
362            expect(log.isTraceEnabled()).andReturn(traceEnabled);
363        }
364    
365        protected final void train_matches(DecoratorDef decoratorDef, ServiceDef serviceDef, boolean matches)
366        {
367            expect(decoratorDef.matches(serviceDef)).andReturn(matches);
368        }
369    
370        protected final void train_matches(AdvisorDef advisorDef, ServiceDef serviceDef, boolean matches)
371        {
372            expect(advisorDef.matches(serviceDef)).andReturn(matches);
373        }
374    
375        protected final <T> void train_provide(ObjectProvider provider, Class<T> objectType,
376                AnnotationProvider annotationProvider, ObjectLocator locator, T object)
377        {
378            expect(provider.provide(objectType, annotationProvider, locator)).andReturn(object);
379        }
380    
381        protected final void train_toURL(Resource resource, URL url)
382        {
383            expect(resource.toURL()).andReturn(url).atLeastOnce();
384        }
385    
386        protected final <T extends Annotation> void train_getAnnotation(AnnotationProvider annotationProvider,
387                Class<T> annotationClass, T annotation)
388        {
389            expect(annotationProvider.getAnnotation(annotationClass)).andReturn(annotation);
390        }
391    
392        protected final MasterObjectProvider mockMasterObjectProvider()
393        {
394            return newMock(MasterObjectProvider.class);
395        }
396    
397        protected final void train_value(IntermediateType it, Class value)
398        {
399            expect(it.value()).andReturn(value);
400        }
401    
402        protected final IntermediateType newIntermediateType()
403        {
404            return newMock(IntermediateType.class);
405        }
406    
407        protected final PropertyAdapter mockPropertyAdapter()
408        {
409            return newMock(PropertyAdapter.class);
410        }
411    
412        protected final ClassPropertyAdapter mockClassPropertyAdapter()
413        {
414            return newMock(ClassPropertyAdapter.class);
415        }
416    
417        protected final PropertyAccess mockPropertyAccess()
418        {
419            return newMock(PropertyAccess.class);
420        }
421    
422        protected final <T> void train_autobuild(ObjectLocator locator, Class<T> beanClass, T instance)
423        {
424            expect(locator.autobuild(beanClass)).andReturn(instance);
425        }
426    
427        protected final PerthreadManager mockPerthreadManager()
428        {
429            return newMock(PerthreadManager.class);
430        }
431    
432        protected final ServiceResources mockServiceResources(OperationTracker tracker)
433        {
434            ServiceResources resources = mockServiceResources();
435    
436            train_getTracker(resources, tracker);
437    
438            return resources;
439        }
440    
441        protected final void train_getTracker(ServiceResources resources, OperationTracker tracker)
442        {
443            expect(resources.getTracker()).andReturn(tracker).atLeastOnce();
444        }
445    
446        protected final ServiceBuilderResources mockServiceBuilderResources(OperationTracker tracker)
447        {
448            ServiceBuilderResources resources = mockServiceBuilderResources();
449    
450            train_getTracker(resources, tracker);
451    
452            return resources;
453        }
454    
455        protected final void train_valueForSymbol(SymbolSource symbolSource, String symbolName, String value)
456        {
457            expect(symbolSource.valueForSymbol(symbolName)).andReturn(value).atLeastOnce();
458        }
459    
460        /**
461         * Touches the file, changing the last modified time to the current time.
462         * Does not return until the last modified time for the file actually changes (how long that takes
463         * is JDK, OS and file system dependent).
464         */
465        protected final void touch(File f) throws Exception
466        {
467            long startModified = f.lastModified();
468    
469            int index = 0;
470    
471            while (true)
472            {
473                f.setLastModified(System.currentTimeMillis());
474    
475                long newModified = f.lastModified();
476    
477                if (newModified != startModified)
478                    return;
479    
480                // Sleep an ever increasing amount, to ensure that the filesystem
481                // catches the change to the file. The Ubuntu CI Server appears
482                // to need longer waits.
483    
484                sleep(50 * (2 ^ index++));
485            }
486        }
487    }