1/* 2 * Copyright (c) 2016 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5package org.mockito.internal.creation.bytebuddy; 6 7import net.bytebuddy.implementation.bind.annotation.*; 8import org.mockito.internal.InternalMockHandler; 9import org.mockito.internal.creation.DelegatingMethod; 10import org.mockito.internal.invocation.MockitoMethod; 11import org.mockito.internal.invocation.SerializableMethod; 12import org.mockito.internal.progress.SequenceNumber; 13import org.mockito.invocation.MockHandler; 14import org.mockito.mock.MockCreationSettings; 15 16import java.io.ObjectStreamException; 17import java.io.Serializable; 18import java.lang.reflect.Method; 19import java.util.concurrent.Callable; 20 21public class MockMethodInterceptor implements Serializable { 22 23 private static final long serialVersionUID = 7152947254057253027L; 24 25 final InternalMockHandler handler; 26 27 private final MockCreationSettings mockCreationSettings; 28 29 private final ByteBuddyCrossClassLoaderSerializationSupport serializationSupport; 30 31 public MockMethodInterceptor(InternalMockHandler handler, MockCreationSettings mockCreationSettings) { 32 this.handler = handler; 33 this.mockCreationSettings = mockCreationSettings; 34 serializationSupport = new ByteBuddyCrossClassLoaderSerializationSupport(); 35 } 36 37 Object doIntercept(Object mock, 38 Method invokedMethod, 39 Object[] arguments, 40 InterceptedInvocation.SuperMethod superMethod) throws Throwable { 41 return handler.handle(new InterceptedInvocation( 42 mock, 43 createMockitoMethod(invokedMethod), 44 arguments, 45 superMethod, 46 SequenceNumber.next() 47 )); 48 } 49 50 private MockitoMethod createMockitoMethod(Method method) { 51 if (mockCreationSettings.isSerializable()) { 52 return new SerializableMethod(method); 53 } else { 54 return new DelegatingMethod(method); 55 } 56 } 57 58 public MockHandler getMockHandler() { 59 return handler; 60 } 61 62 public ByteBuddyCrossClassLoaderSerializationSupport getSerializationSupport() { 63 return serializationSupport; 64 } 65 66 public static class ForHashCode { 67 68 @SuppressWarnings("unused") 69 public static int doIdentityHashCode(@This Object thiz) { 70 return System.identityHashCode(thiz); 71 } 72 } 73 74 public static class ForEquals { 75 76 @SuppressWarnings("unused") 77 public static boolean doIdentityEquals(@This Object thiz, @Argument(0) Object other) { 78 return thiz == other; 79 } 80 } 81 82 public static class ForWriteReplace { 83 84 public static Object doWriteReplace(@This MockAccess thiz) throws ObjectStreamException { 85 return thiz.getMockitoInterceptor().getSerializationSupport().writeReplace(thiz); 86 } 87 } 88 89 public static class DispatcherDefaultingToRealMethod { 90 91 @SuppressWarnings("unused") 92 @RuntimeType 93 @BindingPriority(BindingPriority.DEFAULT * 2) 94 public static Object interceptSuperCallable(@This Object mock, 95 @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor, 96 @Origin Method invokedMethod, 97 @AllArguments Object[] arguments, 98 @SuperCall(serializableProxy = true) Callable<?> superCall) throws Throwable { 99 if (interceptor == null) { 100 return superCall.call(); 101 } 102 return interceptor.doIntercept( 103 mock, 104 invokedMethod, 105 arguments, 106 new InterceptedInvocation.SuperMethod.FromCallable(superCall) 107 ); 108 } 109 110 @SuppressWarnings("unused") 111 @RuntimeType 112 public static Object interceptAbstract(@This Object mock, 113 @FieldValue("mockitoInterceptor") MockMethodInterceptor interceptor, 114 @StubValue Object stubValue, 115 @Origin Method invokedMethod, 116 @AllArguments Object[] arguments) throws Throwable { 117 if (interceptor == null) { 118 return stubValue; 119 } 120 return interceptor.doIntercept( 121 mock, 122 invokedMethod, 123 arguments, 124 InterceptedInvocation.SuperMethod.IsIllegal.INSTANCE 125 ); 126 } 127 } 128} 129