001: package org.codehaus.groovy.runtime;
002:
003: import java.lang.reflect.InvocationHandler;
004: import java.lang.reflect.InvocationTargetException;
005: import java.lang.reflect.Method;
006:
007: /**
008: * This class is a general adapter to map a call to an Java interface
009: * to a given delegate.
010: * <p>
011: * @author Ben Yu
012: * @author <a href="mailto:blackdrag@gmx.org">Jochen Theodorou</a>
013: */
014: public abstract class ConversionHandler implements InvocationHandler {
015: private Object delegate;
016:
017: /**
018: * Creates a ConversionHandler with an deleagte.
019: * @param delegate the delegate
020: * @throws IllegalArgumentException if the given delegate is null
021: */
022: public ConversionHandler(Object delegate) {
023: if (delegate == null)
024: throw new IllegalArgumentException(
025: "delegate must not be null");
026: this .delegate = delegate;
027: }
028:
029: /**
030: * gets the delegate.
031: * @return the delegate
032: */
033: public Object getDelegate() {
034: return delegate;
035: }
036:
037: /**
038: * This method is a default implementation for the invoke method
039: * given in Invocationhandler. Any call to an method with an
040: * declaring class that is not Object is redirected to invokeCustom.
041: * Methods like tostring, equals and hashcode are called on the class
042: * itself instead of the delegate. It is better to overwrite the
043: * invokeCustom method where the Object related methods are filtered out.
044: *
045: * @see #invokeCustom(Object, Method, Object[])
046: * @see InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
047: *
048: * @param proxy the proxy
049: * @param method the method
050: * @param args the arguments
051: * @return the result of the invocation by method or delegate
052: * @throws Throwable any exception caused by the delegate or the method
053: */
054: public Object invoke(Object proxy, Method method, Object[] args)
055: throws Throwable {
056: if (!isObjectMethod(method)) {
057: return invokeCustom(proxy, method, args);
058: }
059: try {
060: return method.invoke(this , args);
061: } catch (InvocationTargetException ite) {
062: throw ite.getTargetException();
063: }
064: }
065:
066: /**
067: * This method is called for all Methods not defined on Object.
068: * The delegate should be called here.
069: *
070: * @param proxy the proxy
071: * @param method the method
072: * @param args the arguments
073: * @return the result of the invocation of the delegate
074: * @throws Throwable any exception causes by the delegate
075: * @see #invoke(Object, Method, Object[])
076: * @see InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
077: *
078: */
079: public abstract Object invokeCustom(Object proxy, Method method,
080: Object[] args) throws Throwable;
081:
082: /**
083: * Indicates whether some other object is "equal to" this one.
084: * The delegate is used if the class of the parameter and the
085: * current class are equal. In other cases the method will return
086: * false. The exact class is here used, if inheritance is needed,
087: * this method must be overwritten.
088: *
089: * @see java.lang.Object#equals(java.lang.Object)
090: */
091: public boolean equals(Object obj) {
092: if (obj != null && obj.getClass() == this .getClass()) {
093: return (((ConversionHandler) obj).getDelegate())
094: .equals(obj);
095: } else {
096: return false;
097: }
098: }
099:
100: /**
101: * Returns a hash code value for the delegate.
102: * @see java.lang.Object#hashCode()
103: */
104: public int hashCode() {
105: return delegate.hashCode();
106: }
107:
108: /**
109: * Returns a String version of the delegate.
110: * @see java.lang.Object#toString()
111: */
112: public String toString() {
113: return delegate.toString();
114: }
115:
116: private static boolean isObjectMethod(Method mtd) {
117: return mtd.getDeclaringClass().equals(Object.class);
118: }
119: }
|