1/* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5package org.mockito.internal.configuration; 6 7import org.mockito.Captor; 8import org.mockito.Mock; 9import org.mockito.MockitoAnnotations; 10import org.mockito.configuration.AnnotationEngine; 11import org.mockito.exceptions.Reporter; 12import org.mockito.exceptions.base.MockitoException; 13import org.mockito.internal.util.reflection.FieldSetter; 14 15import java.lang.annotation.Annotation; 16import java.lang.reflect.Field; 17import java.util.HashMap; 18import java.util.Map; 19 20/** 21 * Initializes fields annotated with @{@link org.mockito.Mock} or @{@link org.mockito.Captor}. 22 * 23 * <p> 24 * The {@link #process(Class, Object)} method implementation <strong>does not</strong> process super classes! 25 * 26 * @see MockitoAnnotations 27 */ 28@SuppressWarnings("unchecked") 29public class DefaultAnnotationEngine implements AnnotationEngine { 30 private final Map<Class<? extends Annotation>, FieldAnnotationProcessor<?>> annotationProcessorMap = new HashMap<Class<? extends Annotation>, FieldAnnotationProcessor<?>>(); 31 32 public DefaultAnnotationEngine() { 33 registerAnnotationProcessor(Mock.class, new MockAnnotationProcessor()); 34 registerAnnotationProcessor(MockitoAnnotations.Mock.class, new MockitoAnnotationsMockAnnotationProcessor()); 35 registerAnnotationProcessor(Captor.class, new CaptorAnnotationProcessor()); 36 } 37 38 /* (non-Javadoc) 39 * @see org.mockito.AnnotationEngine#createMockFor(java.lang.annotation.Annotation, java.lang.reflect.Field) 40 */ 41 @SuppressWarnings("deprecation") 42 public Object createMockFor(Annotation annotation, Field field) { 43 return forAnnotation(annotation).process(annotation, field); 44 } 45 46 private <A extends Annotation> FieldAnnotationProcessor<A> forAnnotation(A annotation) { 47 if (annotationProcessorMap.containsKey(annotation.annotationType())) { 48 return (FieldAnnotationProcessor<A>) annotationProcessorMap.get(annotation.annotationType()); 49 } 50 return new FieldAnnotationProcessor<A>() { 51 public Object process(A annotation, Field field) { 52 return null; 53 } 54 }; 55 } 56 57 private <A extends Annotation> void registerAnnotationProcessor(Class<A> annotationClass, FieldAnnotationProcessor<A> fieldAnnotationProcessor) { 58 annotationProcessorMap.put(annotationClass, fieldAnnotationProcessor); 59 } 60 61 public void process(Class<?> clazz, Object testInstance) { 62 Field[] fields = clazz.getDeclaredFields(); 63 for (Field field : fields) { 64 boolean alreadyAssigned = false; 65 for(Annotation annotation : field.getAnnotations()) { 66 Object mock = createMockFor(annotation, field); 67 if (mock != null) { 68 throwIfAlreadyAssigned(field, alreadyAssigned); 69 alreadyAssigned = true; 70 try { 71 new FieldSetter(testInstance, field).set(mock); 72 } catch (Exception e) { 73 throw new MockitoException("Problems setting field " + field.getName() + " annotated with " 74 + annotation, e); 75 } 76 } 77 } 78 } 79 } 80 81 void throwIfAlreadyAssigned(Field field, boolean alreadyAssigned) { 82 if (alreadyAssigned) { 83 new Reporter().moreThanOneAnnotationNotAllowed(field.getName()); 84 } 85 } 86 87}