001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2007-2012 Pentaho 008// All Rights Reserved. 009*/ 010package mondrian.util; 011 012import java.lang.reflect.*; 013 014/** 015 * A class derived from <code>DelegatingInvocationHandler</code> handles a 016 * method call by looking for a method in itself with identical parameters. If 017 * no such method is found, it forwards the call to a fallback object, which 018 * must implement all of the interfaces which this proxy implements. 019 * 020 * <p>It is useful in creating a wrapper class around an interface which may 021 * change over time.</p> 022 * 023 * <p>Example: 024 * 025 * <blockquote> 026 * <pre>import java.sql.Connection; 027 * Connection connection = ...; 028 * Connection tracingConnection = (Connection) Proxy.newProxyInstance( 029 * null, 030 * new Class[] {Connection.class}, 031 * new DelegatingInvocationHandler() { 032 * protected Object getTarget() { 033 * return connection; 034 * } 035 * Statement createStatement() { 036 * System.out.println("statement created"); 037 * return connection.createStatement(); 038 * } 039 * });</pre> 040 * </blockquote> 041 * </p> 042 * 043 * @author jhyde 044 */ 045public abstract class DelegatingInvocationHandler 046 implements InvocationHandler 047{ 048 public Object invoke( 049 Object proxy, 050 Method method, 051 Object [] args) 052 throws Throwable 053 { 054 Class clazz = getClass(); 055 Method matchingMethod; 056 try { 057 matchingMethod = 058 clazz.getMethod( 059 method.getName(), 060 method.getParameterTypes()); 061 } catch (NoSuchMethodException e) { 062 matchingMethod = null; 063 } catch (SecurityException e) { 064 matchingMethod = null; 065 } 066 try { 067 if (matchingMethod != null) { 068 // Invoke the method in the derived class. 069 return matchingMethod.invoke(this, args); 070 } 071 final Object target = getTarget(); 072 if (target == null) { 073 throw new UnsupportedOperationException( 074 "method: " + method); 075 } 076 return method.invoke( 077 target, 078 args); 079 } catch (InvocationTargetException e) { 080 throw e.getTargetException(); 081 } 082 } 083 084 /** 085 * Returns the object to forward method calls to, should the derived class 086 * not implement the method. Generally, this object will be a member of the 087 * derived class, supplied as a parameter to its constructor. 088 * 089 * <p>The default implementation returns null, which will cause the 090 * {@link #invoke(Object, java.lang.reflect.Method, Object[])} method 091 * to throw an {@link UnsupportedOperationException} if the derived class 092 * does not have the required method. 093 * 094 * @return object to forward method calls to 095 * 096 * @throws InvocationTargetException if there is an error acquiring the 097 * target 098 */ 099 protected Object getTarget() throws InvocationTargetException { 100 return null; 101 } 102} 103 104// End DelegatingInvocationHandler.java