Home | History | Annotate | Download | only in mockito
      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 
     38     public InvocationHandlerAdapter(MockHandler handler) {
     39         this.handler = handler;
     40     }
     41 
     42     @Override
     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 
     57     public MockHandler getHandler() {
     58         return handler;
     59     }
     60 
     61     public void setHandler(MockHandler handler) {
     62         this.handler = handler;
     63     }
     64 
     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 
     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 
     79         ProxiedMethod(Method method) {
     80             this.method = method;
     81         }
     82 
     83         @Override
     84         public String getName() {
     85             return method.getName();
     86         }
     87 
     88         @Override
     89         public Class<?> getReturnType() {
     90             return method.getReturnType();
     91         }
     92 
     93         @Override
     94         public Class<?>[] getParameterTypes() {
     95             return method.getParameterTypes();
     96         }
     97 
     98         @Override
     99         public Class<?>[] getExceptionTypes() {
    100             return method.getExceptionTypes();
    101         }
    102 
    103         @Override
    104         public boolean isVarArgs() {
    105             return method.isVarArgs();
    106         }
    107 
    108         @Override
    109         public Method getJavaMethod() {
    110             return method;
    111         }
    112 
    113         @Override
    114         public Object invoke(Object target, Object[] arguments) throws Throwable {
    115             return ProxyBuilder.callSuper(target, method, arguments);
    116         }
    117 
    118         @Override
    119         public boolean isAbstract() {
    120             return Modifier.isAbstract(method.getModifiers());
    121         }
    122     }
    123 }
    124