/*
* Copyright 2006-2007 The Scriptella Project Team.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* A dynamic proxy adapter which allows overriding several
* methods of a target proxy.
* <p>To create a proxy adapter for Interface, create subclass of
* ProxyAdapter and define methods from Interface you want to handle,
* other methods invocations will be failed.
*
* @author Fyodor Kupolov
* @version 1.0
*/
public class ProxyAdapter<T> {
private final T proxy;
@SuppressWarnings("unchecked")
public ProxyAdapter(Class... interfaces) {
proxy = (T) Proxy.newProxyInstance(getClass().getClassLoader(), interfaces, new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Method m;
try {
//Determine if the method has been defined in a subclass
m = ProxyAdapter.this.getClass().getMethod(method.getName(), method.getParameterTypes());
m.setAccessible(true);
} catch (Exception e) { //if not found
throw new UnsupportedOperationException(method.toString(), e);
}
//Invoke the method found and return the result
try {
return m.invoke(ProxyAdapter.this, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
});
}
/**
* @return proxy instance implementing T.
*/
public T getProxy() {
return proxy;
}
/**
* Usage example
*/
public static void main(String[] args) throws Exception {
//Create adapter for Appendable
ProxyAdapter<Appendable> pa = new ProxyAdapter(Appendable.class) {
private StringBuilder sb = new StringBuilder();
//Override only 2 methods: append and toString
public Appendable append(char c) {
System.out.println("Proxy append(char c) method. Append "+c);
sb.append(c);
return (Appendable) getProxy();
}
public String toString() {
return "Proxy toString method: "+sb;
}
};
final Appendable a = pa.getProxy();
a.append('1').append('2');
System.out.println("a.toString() = " + a.toString());
//this invocation fails because no method has been created
a.append("Not implemented");
}
}
|