1 /*
2  * Copyright 2010-2020 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 package com.amazonaws.http.conn;
16
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.apache.http.conn.ConnectionRequest;
20 import org.apache.http.conn.HttpClientConnectionManager;
21 import org.apache.http.pool.ConnPoolControl;
22
23 import java.lang.reflect.InvocationHandler;
24 import java.lang.reflect.InvocationTargetException;
25 import java.lang.reflect.Method;
26 import java.lang.reflect.Proxy;
27
28 public class ClientConnectionManagerFactory {
29     private static final Log log = LogFactory.getLog(ClientConnectionManagerFactory.class);
30
31     /**
32      * Returns a wrapped instance of {@link HttpClientConnectionManager}
33      * to capture the necessary performance metrics.
34      *
35      * @param orig the target instance to be wrapped
36      */

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

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