/* * Copyright (c) 2016 Mockito contributors * This program is made available under the terms of the MIT License. */ package org.mockito.internal.creation.bytebuddy; import net.bytebuddy.implementation.bind.annotation.*; import org.mockito.internal.InternalMockHandler; import org.mockito.internal.creation.DelegatingMethod; import org.mockito.internal.invocation.MockitoMethod; import org.mockito.internal.invocation.SerializableMethod; import org.mockito.internal.progress.SequenceNumber; import org.mockito.invocation.MockHandler; import org.mockito.mock.MockCreationSettings; import java.io.ObjectStreamException; import java.io.Serializable; import java.lang.reflect.Method; import java.util.concurrent.Callable; public class MockMethodInterceptor implements Serializable { private static final long serialVersionUID = 7152947254057253027L; final InternalMockHandler handler; private final MockCreationSettings mockCreationSettings; private final ByteBuddyCrossClassLoaderSerializationSupport serializationSupport; public MockMethodInterceptor(InternalMockHandler handler, MockCreationSettings mockCreationSettings) { this.handler = handler; this.mockCreationSettings = mockCreationSettings; serializationSupport = new ByteBuddyCrossClassLoaderSerializationSupport(); } Object doIntercept(Object mock, Method invokedMethod, Object[] arguments, InterceptedInvocation.SuperMethod superMethod) throws Throwable { return handler.handle(new InterceptedInvocation( mock, createMockitoMethod(invokedMethod), arguments, superMethod, SequenceNumber.next() )); } private MockitoMethod createMockitoMethod(Method method) { if (mockCreationSettings.isSerializable()) { return new SerializableMethod(method); } else { return new DelegatingMethod(method); } } public MockHandler getMockHandler() { return handler; } public ByteBuddyCrossClassLoaderSerializationSupport getSerializationSupport() { return serializationSupport; } public static class ForHashCode { @SuppressWarnings("unused") public static int doIdentityHashCode(@This Object thiz) { return System.identityHashCode(thiz); } } public static class ForEquals { @SuppressWarnings("unused") public static boolean doIdentityEquals(@This Object thiz, @Argument(0) Object other) { return thiz == other; } } public static class ForWriteReplace { public static Object doWriteReplace(@This MockAccess thiz) throws ObjectStreamException { return thiz.getMockitoInterceptor().getSerializationSupport().writeReplace(thiz); } } public static class DispatcherDefaultingToRealMethod { @SuppressWarnings("unused") @RuntimeType @BindingPriority(BindingPriority.DEFAULT * 2) public static Object interceptSuperCallable(@This Object mock, @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor, @Origin Method invokedMethod, @AllArguments Object[] arguments, @SuperCall(serializableProxy = true) Callable<?> superCall) throws Throwable { if (interceptor == null) { return superCall.call(); } return interceptor.doIntercept( mock, invokedMethod, arguments, new InterceptedInvocation.SuperMethod.FromCallable(superCall) ); } @SuppressWarnings("unused") @RuntimeType public static Object interceptAbstract(@This Object mock, @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor, @StubValue Object stubValue, @Origin Method invokedMethod, @AllArguments Object[] arguments) throws Throwable { if (interceptor == null) { return stubValue; } return interceptor.doIntercept( mock, invokedMethod, arguments, InterceptedInvocation.SuperMethod.IsIllegal.INSTANCE ); } } }