View Javadoc
1   /*
2    * Licensed under the Apache License, Version 2.0 (the "License");
3    * you may not use this file except in compliance with the License.
4    * You may obtain a copy of the License at
5    *
6    *     http://www.apache.org/licenses/LICENSE-2.0
7    *
8    * Unless required by applicable law or agreed to in writing, software
9    * distributed under the License is distributed on an "AS IS" BASIS,
10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11   * See the License for the specific language governing permissions and
12   * limitations under the License.
13   */
14  package org.gbif.ws.client;
15  
16  import java.lang.reflect.InvocationHandler;
17  import java.lang.reflect.Method;
18  import java.lang.reflect.Proxy;
19  import java.util.Map;
20  import java.util.Optional;
21  
22  import feign.InvocationHandlerFactory;
23  import feign.Target;
24  
25  import static feign.Util.checkNotNull;
26  
27  @SuppressWarnings("unused")
28  public class ClientInvocationHandlerFactory implements InvocationHandlerFactory {
29  
30    @Override
31    public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
32      return new ClientInvocationHandlerFactory.FeignInvocationHandler(target, dispatch);
33    }
34  
35    static class FeignInvocationHandler implements InvocationHandler {
36  
37      private final Target target;
38      private final Map<Method, MethodHandler> dispatch;
39  
40      FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {
41        this.target = checkNotNull(target, "target");
42        this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);
43      }
44  
45      @Override
46      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
47        if ("equals".equals(method.getName())) {
48          try {
49            Object otherHandler =
50                args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
51            return equals(otherHandler);
52          } catch (IllegalArgumentException e) {
53            return false;
54          }
55        } else if ("hashCode".equals(method.getName())) {
56          return hashCode();
57        } else if ("toString".equals(method.getName())) {
58          return toString();
59        }
60  
61        return getMethodHandler(method).invoke(args);
62      }
63  
64      private MethodHandler getMethodHandler(Method method) {
65        MethodHandler methodHandler = dispatch.get(method);
66  
67        // if the result is not null just return the handler
68        if (methodHandler != null) {
69          return methodHandler;
70        }
71  
72        // if not we have to find another handler
73        Optional<Method> anotherMethod =
74            dispatch.keySet().stream()
75                .filter(methodFromDispatch -> !methodFromDispatch.equals(method))
76                .filter(methodFromDispatch -> methodFromDispatch.getName().equals(method.getName()))
77                .filter(
78                    methodFromDispatch ->
79                        methodFromDispatch.getParameterCount() == method.getParameterCount())
80                .findFirst();
81  
82        return anotherMethod.map(dispatch::get).orElse(null);
83      }
84  
85      @Override
86      public boolean equals(Object obj) {
87        if (obj instanceof ClientInvocationHandlerFactory.FeignInvocationHandler) {
88          ClientInvocationHandlerFactory.FeignInvocationHandler other =
89              (ClientInvocationHandlerFactory.FeignInvocationHandler) obj;
90          return target.equals(other.target);
91        }
92        return false;
93      }
94  
95      @Override
96      public int hashCode() {
97        return target.hashCode();
98      }
99  
100     @Override
101     public String toString() {
102       return target.toString();
103     }
104   }
105 }