001package org.nuxeo.runtime.javaagent;
002
003import java.lang.reflect.InvocationHandler;
004import java.lang.reflect.Method;
005import java.lang.reflect.Proxy;
006import java.util.HashMap;
007import java.util.Map;
008
009public class AgentHandler implements InvocationHandler {
010
011    public static <I> I newHandler(Class<I> type, Object agent) {
012        return type.cast(Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
013                new Class<?>[] { type }, new AgentHandler(agent)));
014    }
015
016    protected AgentHandler(Object agent) {
017        this.agent = agent;
018        type = agent.getClass();
019    }
020
021    protected final Class<?> type;
022
023    protected final Object agent;
024
025    @Override
026    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
027        if ("humanReadable".equals(method.getName())) {
028            return humanReadable((long) args[0]);
029        }
030        return agentMethod(method).invoke(agent, args);
031    }
032
033    protected static String[] units = { "b", "Kb", "Mb" };
034
035    protected String humanReadable(long size) {
036        String unit = "b";
037        double dSize = size;
038        for (String eachUnit : units) {
039            unit = eachUnit;
040            if (dSize < 1024) {
041                break;
042            }
043            dSize /= 1024;
044        }
045
046        return dSize + unit;
047    }
048
049    protected final Map<Method, Method> agentMethods = new HashMap<>();
050
051    protected Method agentMethod(Method bridgeMethod) throws NoSuchMethodException, SecurityException {
052        Method agentMethod = agentMethods.get(bridgeMethod);
053        if (agentMethod == null) {
054            agentMethod = type.getDeclaredMethod(bridgeMethod.getName(), bridgeMethod.getParameterTypes());
055            agentMethods.put(bridgeMethod, agentMethod);
056        }
057        return agentMethod;
058    }
059
060}