/**
* Copyright (c) 2013-2016, The SeedStack authors <http://seedstack.org>
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.seedstack.seed.core.internal.dependency;
import org.seedstack.seed.SeedException;
import org.seedstack.seed.core.internal.CoreErrorCode;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* Proxy to implement interfaces. Override each method to proxy (method from the interface).<br>
* For example: to create a proxy for a Gauge interface
*
* <pre>
* DependencyProxy<Gauge<Long>> pgauge = new DependencyProxy<Gauge<Long>>(new Class[]{Gauge.class}, new ProxyMethodReplacer() {
* public Long getValue(){
* return RandomUtils.nextLong();
* }
* });
*
* </pre>
*
* @param <T> class to proxy
*/
public class DependencyProxy<T> implements InvocationHandler {
private final T proxy;
private final Object substitute;
/**
* Create a proxy with all specified interfaces and override methods with the substitute object.
*
* @param interfaces interfaces for the proxy
* @param substitute the method replacer to override method.
*/
@SuppressWarnings("unchecked")
public DependencyProxy(Class<?>[] interfaces, Object substitute) {
try {
this.proxy = (T) Proxy.newProxyInstance(DependencyProxy.class.getClassLoader(), interfaces, this);
} catch (IllegalArgumentException e) {
throw SeedException.wrap(e, CoreErrorCode.UNABLE_TO_CREATE_PROXY).put("class", interfaces[0].getName());
}
this.substitute = substitute;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m;
try {
m = substitute.getClass().getMethod(method.getName(), method.getParameterTypes());
m.setAccessible(true);
} catch (Exception e) {
throw new UnsupportedOperationException(method.toString(), e);
}
try {
return m.invoke(substitute, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
public T getProxy() {
return proxy;
}
}