1 package org.testng.internal.invokers; 2 3 import org.testng.IInvokedMethod; 4 import org.testng.IInvokedMethodListener; 5 import org.testng.IInvokedMethodListener2; 6 import org.testng.ITestContext; 7 import org.testng.ITestResult; 8 import org.testng.collections.Maps; 9 10 import java.util.Map; 11 12 import static org.testng.internal.invokers.InvokedMethodListenerMethod.AFTER_INVOCATION; 13 import static org.testng.internal.invokers.InvokedMethodListenerMethod.BEFORE_INVOCATION; 14 import static org.testng.internal.invokers.InvokedMethodListenerSubtype.EXTENDED_LISTENER; 15 import static org.testng.internal.invokers.InvokedMethodListenerSubtype.SIMPLE_LISTENER; 16 17 /** 18 * Hides complexity of calling methods of {@link IInvokedMethodListener} and 19 * {@link IInvokedMethodListener2}. 20 * 21 * @author Ansgar Konermann 22 */ 23 public class InvokedMethodListenerInvoker { 24 25 private InvokedMethodListenerMethod m_listenerMethod; 26 private ITestContext m_testContext; 27 private ITestResult m_testResult; 28 29 /** 30 * Creates a new invoker instance which can be used to call the specified {@code listenerMethod} 31 * on any number of {@link IInvokedMethodListener}s. 32 * 33 * @param listenerMethod method which should be called 34 * @param testResult test result which should be passed to the listener method upon invocation 35 * @param testContext test context which should be passed to the listener method upon invocation. 36 * This parameter is only used when calling methods on an {@link IInvokedMethodListener2}. 37 */ InvokedMethodListenerInvoker(InvokedMethodListenerMethod listenerMethod, ITestResult testResult, ITestContext testContext)38 public InvokedMethodListenerInvoker(InvokedMethodListenerMethod listenerMethod, 39 ITestResult testResult, ITestContext testContext) { 40 m_listenerMethod = listenerMethod; 41 m_testContext = testContext; 42 m_testResult = testResult; 43 } 44 45 /** 46 * Invoke the given {@code listenerInstance}, calling the method specified in the constructor of 47 * this {@link InvokedMethodListenerInvoker}. 48 * 49 * @param listenerInstance the listener instance which should be invoked. 50 * @param invokedMethod the {@link IInvokedMethod} instance which should be passed to the 51 * {@link IInvokedMethodListener#beforeInvocation(IInvokedMethod, ITestResult)}, 52 * {@link IInvokedMethodListener#afterInvocation(IInvokedMethod, ITestResult)}, 53 * {@link IInvokedMethodListener2#beforeInvocation(IInvokedMethod, ITestResult, ITestContext)} 54 * or {@link IInvokedMethodListener2#afterInvocation(IInvokedMethod, ITestResult, ITestContext)} 55 * method. 56 */ 57 58 @SuppressWarnings("unchecked") invokeListener(IInvokedMethodListener listenerInstance, IInvokedMethod invokedMethod)59 public void invokeListener(IInvokedMethodListener listenerInstance, 60 IInvokedMethod invokedMethod) { 61 final InvocationStrategy strategy = obtainStrategyFor(listenerInstance, m_listenerMethod); 62 strategy.callMethod(listenerInstance, invokedMethod, m_testResult, m_testContext); 63 } 64 obtainStrategyFor(IInvokedMethodListener listenerInstance, InvokedMethodListenerMethod listenerMethod)65 private InvocationStrategy obtainStrategyFor(IInvokedMethodListener listenerInstance, 66 InvokedMethodListenerMethod listenerMethod) { 67 InvokedMethodListenerSubtype invokedMethodListenerSubtype = InvokedMethodListenerSubtype 68 .fromListener(listenerInstance); 69 Map<InvokedMethodListenerMethod, InvocationStrategy> strategiesForListenerType = strategies 70 .get(invokedMethodListenerSubtype); 71 InvocationStrategy invocationStrategy = strategiesForListenerType.get(listenerMethod); 72 return invocationStrategy; 73 } 74 75 private static interface InvocationStrategy<LISTENER_TYPE extends IInvokedMethodListener> { callMethod(LISTENER_TYPE listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext)76 void callMethod(LISTENER_TYPE listener, IInvokedMethod invokedMethod, ITestResult testResult, 77 ITestContext testContext); 78 } 79 80 private static class InvokeBeforeInvocationWithoutContextStrategy implements 81 InvocationStrategy<IInvokedMethodListener> { callMethod(IInvokedMethodListener listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext)82 public void callMethod(IInvokedMethodListener listener, IInvokedMethod invokedMethod, 83 ITestResult testResult, ITestContext testContext) { 84 listener.beforeInvocation(invokedMethod, testResult); 85 } 86 } 87 88 private static class InvokeBeforeInvocationWithContextStrategy implements 89 InvocationStrategy<IInvokedMethodListener2> { callMethod(IInvokedMethodListener2 listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext)90 public void callMethod(IInvokedMethodListener2 listener, IInvokedMethod invokedMethod, 91 ITestResult testResult, ITestContext testContext) { 92 listener.beforeInvocation(invokedMethod, testResult, testContext); 93 } 94 } 95 96 private static class InvokeAfterInvocationWithoutContextStrategy implements 97 InvocationStrategy<IInvokedMethodListener> { callMethod(IInvokedMethodListener listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext)98 public void callMethod(IInvokedMethodListener listener, IInvokedMethod invokedMethod, 99 ITestResult testResult, ITestContext testContext) { 100 listener.afterInvocation(invokedMethod, testResult); 101 } 102 } 103 104 private static class InvokeAfterInvocationWithContextStrategy implements 105 InvocationStrategy<IInvokedMethodListener2> { callMethod(IInvokedMethodListener2 listener, IInvokedMethod invokedMethod, ITestResult testResult, ITestContext testContext)106 public void callMethod(IInvokedMethodListener2 listener, IInvokedMethod invokedMethod, 107 ITestResult testResult, ITestContext testContext) { 108 listener.afterInvocation(invokedMethod, testResult, testContext); 109 } 110 } 111 112 private static final Map<InvokedMethodListenerSubtype, Map<InvokedMethodListenerMethod, 113 InvocationStrategy>> strategies = Maps.newHashMap(); 114 private static final Map<InvokedMethodListenerMethod, InvocationStrategy> 115 INVOKE_WITH_CONTEXT_STRATEGIES = Maps.newHashMap(); 116 private static final Map<InvokedMethodListenerMethod, InvocationStrategy> 117 INVOKE_WITHOUT_CONTEXT_STRATEGIES = Maps.newHashMap(); 118 119 static { INVOKE_WITH_CONTEXT_STRATEGIES.put(BEFORE_INVOCATION, new InvokeBeforeInvocationWithContextStrategy())120 INVOKE_WITH_CONTEXT_STRATEGIES.put(BEFORE_INVOCATION, 121 new InvokeBeforeInvocationWithContextStrategy()); INVOKE_WITH_CONTEXT_STRATEGIES.put(AFTER_INVOCATION, new InvokeAfterInvocationWithContextStrategy())122 INVOKE_WITH_CONTEXT_STRATEGIES.put(AFTER_INVOCATION, 123 new InvokeAfterInvocationWithContextStrategy()); INVOKE_WITHOUT_CONTEXT_STRATEGIES.put(BEFORE_INVOCATION, new InvokeBeforeInvocationWithoutContextStrategy())124 INVOKE_WITHOUT_CONTEXT_STRATEGIES.put(BEFORE_INVOCATION, 125 new InvokeBeforeInvocationWithoutContextStrategy()); INVOKE_WITHOUT_CONTEXT_STRATEGIES.put(AFTER_INVOCATION, new InvokeAfterInvocationWithoutContextStrategy())126 INVOKE_WITHOUT_CONTEXT_STRATEGIES.put(AFTER_INVOCATION, 127 new InvokeAfterInvocationWithoutContextStrategy()); 128 strategies.put(EXTENDED_LISTENER, INVOKE_WITH_CONTEXT_STRATEGIES)129 strategies.put(EXTENDED_LISTENER, INVOKE_WITH_CONTEXT_STRATEGIES); strategies.put(SIMPLE_LISTENER, INVOKE_WITHOUT_CONTEXT_STRATEGIES)130 strategies.put(SIMPLE_LISTENER, INVOKE_WITHOUT_CONTEXT_STRATEGIES); 131 } 132 } 133