001: /*
002: * Copyright 2006-2007 The Scriptella Project Team.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package scriptella.util;
017:
018: import java.lang.reflect.InvocationHandler;
019: import java.lang.reflect.InvocationTargetException;
020: import java.lang.reflect.Method;
021: import java.lang.reflect.Proxy;
022:
023: /**
024: * A dynamic proxy adapter which allows overriding several
025: * methods of a target proxy.
026: * <p>To create a proxy adapter for Interface, create subclass of
027: * ProxyAdapter and define methods from Interface you want to handle,
028: * other methods invocations will be failed.
029: *
030: * @author Fyodor Kupolov
031: * @version 1.0
032: */
033: public class ProxyAdapter<T> {
034: private final T proxy;
035:
036: @SuppressWarnings("unchecked")
037: public ProxyAdapter(Class... interfaces) {
038: proxy = (T) Proxy.newProxyInstance(getClass().getClassLoader(),
039: interfaces, new InvocationHandler() {
040: public Object invoke(Object proxy, Method method,
041: Object[] args) throws Throwable {
042: Method m;
043: try {
044: //Determine if the method has been defined in a subclass
045: m = ProxyAdapter.this .getClass().getMethod(
046: method.getName(),
047: method.getParameterTypes());
048: m.setAccessible(true);
049: } catch (Exception e) { //if not found
050: throw new UnsupportedOperationException(
051: method.toString(), e);
052:
053: }
054: //Invoke the method found and return the result
055: try {
056: return m.invoke(ProxyAdapter.this , args);
057: } catch (InvocationTargetException e) {
058: throw e.getCause();
059: }
060: }
061: });
062: }
063:
064: /**
065: * @return proxy instance implementing T.
066: */
067: public T getProxy() {
068: return proxy;
069: }
070:
071: /**
072: * Usage example
073: */
074: public static void main(String[] args) throws Exception {
075: //Create adapter for Appendable
076: ProxyAdapter<Appendable> pa = new ProxyAdapter(Appendable.class) {
077: private StringBuilder sb = new StringBuilder();
078:
079: //Override only 2 methods: append and toString
080: public Appendable append(char c) {
081: System.out
082: .println("Proxy append(char c) method. Append "
083: + c);
084: sb.append(c);
085: return (Appendable) getProxy();
086: }
087:
088: public String toString() {
089: return "Proxy toString method: " + sb;
090: }
091:
092: };
093: final Appendable a = pa.getProxy();
094: a.append('1').append('2');
095: System.out.println("a.toString() = " + a.toString());
096: //this invocation fails because no method has been created
097: a.append("Not implemented");
098:
099: }
100: }
|