001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.gbif.ws.client; 015 016import java.lang.reflect.InvocationHandler; 017import java.lang.reflect.Method; 018import java.lang.reflect.Proxy; 019import java.util.Map; 020import java.util.Optional; 021 022import feign.InvocationHandlerFactory; 023import feign.Target; 024 025import static feign.Util.checkNotNull; 026 027@SuppressWarnings("unused") 028public class ClientInvocationHandlerFactory implements InvocationHandlerFactory { 029 030 @Override 031 public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) { 032 return new ClientInvocationHandlerFactory.FeignInvocationHandler(target, dispatch); 033 } 034 035 static class FeignInvocationHandler implements InvocationHandler { 036 037 private final Target target; 038 private final Map<Method, MethodHandler> dispatch; 039 040 FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) { 041 this.target = checkNotNull(target, "target"); 042 this.dispatch = checkNotNull(dispatch, "dispatch for %s", target); 043 } 044 045 @Override 046 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 047 if ("equals".equals(method.getName())) { 048 try { 049 Object otherHandler = 050 args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null; 051 return equals(otherHandler); 052 } catch (IllegalArgumentException e) { 053 return false; 054 } 055 } else if ("hashCode".equals(method.getName())) { 056 return hashCode(); 057 } else if ("toString".equals(method.getName())) { 058 return toString(); 059 } 060 061 return getMethodHandler(method).invoke(args); 062 } 063 064 private MethodHandler getMethodHandler(Method method) { 065 MethodHandler methodHandler = dispatch.get(method); 066 067 // if the result is not null just return the handler 068 if (methodHandler != null) { 069 return methodHandler; 070 } 071 072 // if not we have to find another handler 073 Optional<Method> anotherMethod = 074 dispatch.keySet().stream() 075 .filter(methodFromDispatch -> !methodFromDispatch.equals(method)) 076 .filter(methodFromDispatch -> methodFromDispatch.getName().equals(method.getName())) 077 .filter( 078 methodFromDispatch -> 079 methodFromDispatch.getParameterCount() == method.getParameterCount()) 080 .findFirst(); 081 082 return anotherMethod.map(dispatch::get).orElse(null); 083 } 084 085 @Override 086 public boolean equals(Object obj) { 087 if (obj instanceof ClientInvocationHandlerFactory.FeignInvocationHandler) { 088 ClientInvocationHandlerFactory.FeignInvocationHandler other = 089 (ClientInvocationHandlerFactory.FeignInvocationHandler) obj; 090 return target.equals(other.target); 091 } 092 return false; 093 } 094 095 @Override 096 public int hashCode() { 097 return target.hashCode(); 098 } 099 100 @Override 101 public String toString() { 102 return target.toString(); 103 } 104 } 105}