2
* Copyright (C) 2012 The Guava Authors
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
package com.google.common.testing;
19
import static com.google.common.base.Preconditions.checkNotNull;
20
import static com.google.common.testing.NullPointerTester.isNullable;
22
import com.google.common.annotations.GwtIncompatible;
23
import com.google.common.annotations.J2ktIncompatible;
24
import com.google.common.collect.ImmutableList;
25
import com.google.common.collect.Sets;
26
import com.google.common.reflect.AbstractInvocationHandler;
27
import com.google.common.reflect.Invokable;
28
import com.google.common.reflect.Parameter;
29
import com.google.common.reflect.TypeToken;
30
import java.io.Serializable;
31
import java.lang.reflect.Method;
32
import java.lang.reflect.Proxy;
34
import org.checkerframework.checker.nullness.qual.Nullable;
37
* Generates a dummy interface proxy that simply returns a dummy value for each method.
43
@ElementTypesAreNonnullByDefault
44
abstract class DummyProxy {
47
* Returns a new proxy for {@code interfaceType}. Proxies of the same interface are equal to each
48
* other if the {@link DummyProxy} instance that created the proxies are equal.
50
final <T> T newProxy(TypeToken<T> interfaceType) {
51
Set<Class<?>> interfaceClasses = Sets.newLinkedHashSet();
52
interfaceClasses.addAll(interfaceType.getTypes().interfaces().rawTypes());
53
// Make the proxy serializable to work with SerializableTester
54
interfaceClasses.add(Serializable.class);
56
Proxy.newProxyInstance(
57
interfaceClasses.iterator().next().getClassLoader(),
58
interfaceClasses.toArray(new Class<?>[interfaceClasses.size()]),
59
new DummyHandler(interfaceType));
60
@SuppressWarnings("unchecked") // interfaceType is T
65
/** Returns the dummy return value for {@code returnType}. */
66
abstract <R> @Nullable R dummyReturnValue(TypeToken<R> returnType);
68
private class DummyHandler extends AbstractInvocationHandler implements Serializable {
69
private final TypeToken<?> interfaceType;
71
DummyHandler(TypeToken<?> interfaceType) {
72
this.interfaceType = interfaceType;
76
protected @Nullable Object handleInvocation(
77
Object proxy, Method method, @Nullable Object[] args) {
78
Invokable<?, ?> invokable = interfaceType.method(method);
79
ImmutableList<Parameter> params = invokable.getParameters();
80
for (int i = 0; i < args.length; i++) {
81
Parameter param = params.get(i);
82
if (!isNullable(param)) {
83
checkNotNull(args[i]);
86
return dummyReturnValue(interfaceType.resolveType(method.getGenericReturnType()));
90
public int hashCode() {
91
return identity().hashCode();
95
public boolean equals(@Nullable Object obj) {
96
if (obj instanceof DummyHandler) {
97
DummyHandler that = (DummyHandler) obj;
98
return identity().equals(that.identity());
104
private DummyProxy identity() {
105
return DummyProxy.this;
109
public String toString() {
110
return "Dummy proxy for " + interfaceType;
113
// Since type variables aren't serializable, reduce the type down to raw type before
115
private Object writeReplace() {
116
return new DummyHandler(TypeToken.of(interfaceType.getRawType()));