1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
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  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */

15
16 package software.amazon.awssdk.http.apache.internal.conn;
17
18 import java.lang.reflect.InvocationHandler;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
21 import java.lang.reflect.Proxy;
22 import org.apache.http.conn.ConnectionRequest;
23 import org.apache.http.conn.HttpClientConnectionManager;
24 import org.apache.http.pool.ConnPoolControl;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27 import software.amazon.awssdk.annotations.SdkInternalApi;
28
29 @SdkInternalApi
30 public final class ClientConnectionManagerFactory {
31     private static final Logger log = LoggerFactory.getLogger(ClientConnectionManagerFactory.class);
32
33     private ClientConnectionManagerFactory() {
34     }
35
36     /**
37      * Returns a wrapped instance of {@link HttpClientConnectionManager}
38      * to capture the necessary performance metrics.
39      *
40      * @param orig the target instance to be wrapped
41      */

42     public static HttpClientConnectionManager wrap(HttpClientConnectionManager orig) {
43         if (orig instanceof Wrapped) {
44             throw new IllegalArgumentException();
45         }
46         Class<?>[] interfaces;
47         if (orig instanceof ConnPoolControl) {
48             interfaces = new Class<?>[]{
49                     HttpClientConnectionManager.class,
50                     ConnPoolControl.class,
51                     Wrapped.class};
52         } else {
53             interfaces = new Class<?>[]{
54                     HttpClientConnectionManager.class,
55                     Wrapped.class
56             };
57         }
58         return (HttpClientConnectionManager) Proxy.newProxyInstance(
59                 // https://github.com/aws/aws-sdk-java/pull/48#issuecomment-29454423
60                 ClientConnectionManagerFactory.class.getClassLoader(),
61                 interfaces,
62                 new Handler(orig));
63     }
64
65     /**
66      * The handler behind the dynamic proxy for {@link HttpClientConnectionManager}
67      * so that the any returned instance of {@link ConnectionRequest} can
68      * further wrapped for capturing performance metrics.
69      */

70     private static class Handler implements InvocationHandler {
71         private final HttpClientConnectionManager orig;
72
73         Handler(HttpClientConnectionManager real) {
74             this.orig = real;
75         }
76
77         @Override
78         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
79             try {
80                 Object ret = method.invoke(orig, args);
81                 return ret instanceof ConnectionRequest
82                         ? ClientConnectionRequestFactory.wrap((ConnectionRequest) ret)
83                         : ret
84                         ;
85             } catch (InvocationTargetException e) {
86                 log.debug("", e);
87                 throw e.getCause();
88             }
89         }
90     }
91 }
92