1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 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 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 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. 15 */ 16 17 package com.android.dx.mockito; 18 19 import com.android.dx.stock.ProxyBuilder; 20 import org.mockito.internal.debugging.LocationImpl; 21 import org.mockito.internal.invocation.InvocationImpl; 22 import org.mockito.internal.invocation.MockitoMethod; 23 import org.mockito.internal.invocation.realmethod.RealMethod; 24 import org.mockito.internal.progress.SequenceNumber; 25 import org.mockito.invocation.MockHandler; 26 27 import java.lang.reflect.InvocationHandler; 28 import java.lang.reflect.Method; 29 import java.lang.reflect.Modifier; 30 31 /** 32 * Handles proxy method invocations to dexmaker's InvocationHandler by calling 33 * a MockitoInvocationHandler. 34 */ 35 final class InvocationHandlerAdapter implements InvocationHandler { 36 private MockHandler handler; 37 InvocationHandlerAdapter(MockHandler handler)38 public InvocationHandlerAdapter(MockHandler handler) { 39 this.handler = handler; 40 } 41 42 @Override invoke(Object proxy, Method method, Object[] args)43 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 44 // args can be null if the method invoked has no arguments, but Mockito expects a non-null array 45 args = args != null ? args : new Object[0]; 46 if (isEqualsMethod(method)) { 47 return proxy == args[0]; 48 } else if (isHashCodeMethod(method)) { 49 return System.identityHashCode(proxy); 50 } 51 52 ProxiedMethod proxiedMethod = new ProxiedMethod(method); 53 return handler.handle(new InvocationImpl(proxy, proxiedMethod, args, SequenceNumber.next(), 54 proxiedMethod, new LocationImpl())); 55 } 56 getHandler()57 public MockHandler getHandler() { 58 return handler; 59 } 60 setHandler(MockHandler handler)61 public void setHandler(MockHandler handler) { 62 this.handler = handler; 63 } 64 isEqualsMethod(Method method)65 private static boolean isEqualsMethod(Method method) { 66 return method.getName().equals("equals") 67 && method.getParameterTypes().length == 1 68 && method.getParameterTypes()[0] == Object.class; 69 } 70 isHashCodeMethod(Method method)71 private static boolean isHashCodeMethod(Method method) { 72 return method.getName().equals("hashCode") 73 && method.getParameterTypes().length == 0; 74 } 75 76 private static class ProxiedMethod implements MockitoMethod, RealMethod { 77 private final Method method; 78 ProxiedMethod(Method method)79 ProxiedMethod(Method method) { 80 this.method = method; 81 } 82 83 @Override getName()84 public String getName() { 85 return method.getName(); 86 } 87 88 @Override getReturnType()89 public Class<?> getReturnType() { 90 return method.getReturnType(); 91 } 92 93 @Override getParameterTypes()94 public Class<?>[] getParameterTypes() { 95 return method.getParameterTypes(); 96 } 97 98 @Override getExceptionTypes()99 public Class<?>[] getExceptionTypes() { 100 return method.getExceptionTypes(); 101 } 102 103 @Override isVarArgs()104 public boolean isVarArgs() { 105 return method.isVarArgs(); 106 } 107 108 @Override getJavaMethod()109 public Method getJavaMethod() { 110 return method; 111 } 112 113 @Override invoke(Object target, Object[] arguments)114 public Object invoke(Object target, Object[] arguments) throws Throwable { 115 return ProxyBuilder.callSuper(target, method, arguments); 116 } 117 118 @Override isAbstract()119 public boolean isAbstract() { 120 return Modifier.isAbstract(method.getModifiers()); 121 } 122 } 123 } 124