/* XXL: The eXtensible and fleXible Library for data processing Copyright (C) 2000-2011 Prof. Dr. Bernhard Seeger Head of the Database Research Group Department of Mathematics and Computer Science University of Marburg Germany This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; If not, see <http://www.gnu.org/licenses/>. http://code.google.com/p/xxl/ */ package xxl.core.util.reflect; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * This class wraps a given Object that implements a known interface, * so that all Methods become synchronized. It uses the reflection mechanism that * was introduced with jdk 1.3. */ public class SynchronizedWrapper implements InvocationHandler { /** Object that should be synchronized */ private Object delegate; /** * Produces dynamically a SynchronizedWrapper for the specified interface and object and * returns it. * * @param delegate Object to which the calls are delegated. * @param interfaceName name of the interface * @return returns a SynchronizedWrapper produced * */ public static Object newInstance(Object delegate, String interfaceName) { try { Class c = Class.forName(interfaceName); return Proxy.newProxyInstance( Thread.currentThread().getContextClassLoader(), new Class[] { c }, new SynchronizedWrapper(delegate) ); } catch (ClassNotFoundException e) { return null; } } /** * Creates a SynchronizedWrapper (private!). * * @param delegate Object to which the calls are delegated. */ private SynchronizedWrapper(Object delegate) { this.delegate = delegate; } /** * This method is invoked automatically by the proxy. It is * unusual to call this method directly. * * @param proxy the proxy instance that the method was invoked on * @param meth the Method instance corresponding to the interface method * invoked on the proxy instance. The declaring class of the Method * object will be the interface that the method was declared in, which * may be a superinterface of the proxy interface that the proxy class * inherits the method through. * @param args an array of objects containing the values of the arguments passed * in the method invocation on the proxy instance, or null if interface * method takes no arguments. Arguments of primitive types are wrapped in * instances of the appropriate primitive wrapper class, such as * java.lang.Integer or java.lang.Boolean. * @return the value to return from the method invocation on the proxy instance. * If the declared return type of the interface method is a primitive type, * then the value returned by this method must be an instance of the * corresponding primitive wrapper class; otherwise, it must be a type * assignable to the declared return type. If the value returned by this * method is null and the interface method's return type is primitive, then * a NullPointerException will be thrown by the method invocation on the * proxy instance. If the value returned by this method is otherwise not * compatible with the interface method's declared return type as described * above, a ClassCastException will be thrown by the method invocation on * the proxy instance. * @throws Throwable */ public synchronized Object invoke(Object proxy, Method meth, Object[] args) throws Throwable { try { return meth.invoke(delegate, args); } catch (InvocationTargetException e) { throw e.getTargetException(); } } }