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.invocation;
6
7import org.mockito.exceptions.base.MockitoException;
8
9import java.io.Serializable;
10import java.lang.reflect.Method;
11import java.lang.reflect.Modifier;
12import java.util.Arrays;
13
14public class SerializableMethod implements Serializable, MockitoMethod {
15
16    private static final long serialVersionUID = 6005610965006048445L;
17
18    private final Class<?> declaringClass;
19    private final String methodName;
20    private final Class<?>[] parameterTypes;
21    private final Class<?> returnType;
22    private final Class<?>[] exceptionTypes;
23    private final boolean isVarArgs;
24    private final boolean isAbstract;
25
26    private volatile transient Method method;
27
28    public SerializableMethod(Method method) {
29        this.method = method;
30        declaringClass = method.getDeclaringClass();
31        methodName = method.getName();
32        parameterTypes = method.getParameterTypes();
33        returnType = method.getReturnType();
34        exceptionTypes = method.getExceptionTypes();
35        isVarArgs = method.isVarArgs();
36        isAbstract = (method.getModifiers() & Modifier.ABSTRACT) != 0;
37    }
38
39    public String getName() {
40        return methodName;
41    }
42
43    public Class<?> getReturnType() {
44        return returnType;
45    }
46
47    public Class<?>[] getParameterTypes() {
48        return parameterTypes;
49    }
50
51    public Class<?>[] getExceptionTypes() {
52        return exceptionTypes;
53    }
54
55    public boolean isVarArgs() {
56        return isVarArgs;
57    }
58
59    public boolean isAbstract() {
60        return isAbstract;
61    }
62
63    public Method getJavaMethod() {
64        if (method != null) {
65            return method;
66        }
67        try {
68            method = declaringClass.getDeclaredMethod(methodName, parameterTypes);
69            return method;
70        } catch (SecurityException e) {
71            String message = String.format(
72                    "The method %1$s.%2$s is probably private or protected and cannot be mocked.\n" +
73                            "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);
74            throw new MockitoException(message, e);
75        } catch (NoSuchMethodException e) {
76            String message = String.format(
77                    "The method %1$s.%2$s does not exists and you should not get to this point.\n" +
78                            "Please report this as a defect with an example of how to reproduce it.", declaringClass, methodName);
79            throw new MockitoException(message, e);
80        }
81    }
82
83    @Override
84    public int hashCode() {
85        return 1;
86    }
87
88    @Override
89    public boolean equals(Object obj) {
90        if (this == obj)
91            return true;
92        if (obj == null)
93            return false;
94        if (getClass() != obj.getClass())
95            return false;
96        SerializableMethod other = (SerializableMethod) obj;
97        if (declaringClass == null) {
98            if (other.declaringClass != null)
99                return false;
100        } else if (!declaringClass.equals(other.declaringClass))
101            return false;
102        if (methodName == null) {
103            if (other.methodName != null)
104                return false;
105        } else if (!methodName.equals(other.methodName))
106            return false;
107        if (!Arrays.equals(parameterTypes, other.parameterTypes))
108            return false;
109        if (returnType == null) {
110            if (other.returnType != null)
111                return false;
112        } else if (!returnType.equals(other.returnType))
113            return false;
114        return true;
115    }
116}
117