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.handler;
6
7import static org.mockito.internal.exceptions.Reporter.invocationListenerThrewException;
8
9import java.util.List;
10import org.mockito.internal.InternalMockHandler;
11import org.mockito.internal.stubbing.InvocationContainer;
12import org.mockito.invocation.Invocation;
13import org.mockito.invocation.MockHandler;
14import org.mockito.listeners.InvocationListener;
15import org.mockito.mock.MockCreationSettings;
16import org.mockito.stubbing.Answer;
17
18/**
19 * Handler, that call all listeners wanted for this mock, before delegating it
20 * to the parameterized handler.
21 *
22 * Also imposterize MockHandlerImpl, delegate all call of InternalMockHandler to the real mockHandler
23 */
24class InvocationNotifierHandler<T> implements MockHandler, InternalMockHandler<T> {
25
26    private final List<InvocationListener> invocationListeners;
27    private final InternalMockHandler<T> mockHandler;
28
29    public InvocationNotifierHandler(InternalMockHandler<T> mockHandler, MockCreationSettings<T> settings) {
30        this.mockHandler = mockHandler;
31        this.invocationListeners = settings.getInvocationListeners();
32    }
33
34    public Object handle(Invocation invocation) throws Throwable {
35        try {
36            Object returnedValue = mockHandler.handle(invocation);
37            notifyMethodCall(invocation, returnedValue);
38            return returnedValue;
39        } catch (Throwable t){
40            notifyMethodCallException(invocation, t);
41            throw t;
42        }
43    }
44
45
46    private void notifyMethodCall(Invocation invocation, Object returnValue) {
47        for (InvocationListener listener : invocationListeners) {
48            try {
49                listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, returnValue));
50            } catch(Throwable listenerThrowable) {
51                throw invocationListenerThrewException(listener, listenerThrowable);
52            }
53        }
54    }
55
56    private void notifyMethodCallException(Invocation invocation, Throwable exception) {
57        for (InvocationListener listener : invocationListeners) {
58            try {
59                listener.reportInvocation(new NotifiedMethodInvocationReport(invocation, exception));
60            } catch(Throwable listenerThrowable) {
61                throw invocationListenerThrewException(listener, listenerThrowable);
62            }
63        }
64    }
65
66    public MockCreationSettings<T> getMockSettings() {
67        return mockHandler.getMockSettings();
68    }
69
70    public void setAnswersForStubbing(List<Answer<?>> answers) {
71        mockHandler.setAnswersForStubbing(answers);
72    }
73
74    public InvocationContainer getInvocationContainer() {
75        return mockHandler.getInvocationContainer();
76    }
77
78}
79