cat.albirar.framework.proxy.ProxyFactory.java Source code

Java tutorial

Introduction

Here is the source code for cat.albirar.framework.proxy.ProxyFactory.java

Source

/*
 * This file is part of "albirar framework".
 * 
 * "albirar framework" is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * "albirar framework" 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 General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with calendar.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright (C) 2013 Octavi Forns
 */

package cat.albirar.framework.proxy;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.util.Assert;

/**
 * A factory to create proxies for interfaces or classes.
 * Use a JDK Dynamic Proxy if the type is an interface.
 * Use a CGLib proxy if the type is a concrete class.
 * 
 * @author Octavi Forns ofornes@albirar.cat
 * @since 2.1.0
 */
public class ProxyFactory {
    private static ProxyFactory singleton;

    /**
     * Factory instantiation method.
     * @return A singleton proxy factory
     */
    public static ProxyFactory instanceProxy() {
        if (singleton == null) {
            singleton = new ProxyFactory();
        }
        return singleton;
    }

    /**
     * Create a proxy for the indicated type, tied to the indicated type.
     * @param handler The handler, required
     * @param type
     * @return the new type
     */
    public <T> T newProxy(IProxyHandler handler, Class<T> type) {
        Assert.notNull(handler, "Handler is required");
        Assert.notNull(type, "Type is required");
        if (type.isInterface()) {
            return newProxyForInterface(new ProxyInvocationHandlerWrapper(handler), type);
        }
        return newProxyForConcreteClass(new ProxyInvocationHandlerWrapper(handler), type);
    }

    /**
     * Create a proxy for the indicated type.
     * @param handler The handler
     * @param type The type, should to be a concrete class type
     * @return The proxy
     */
    @SuppressWarnings("unchecked")
    private <T> T newProxyForConcreteClass(org.springframework.cglib.proxy.Callback handler, Class<T> type) {
        Enhancer enhancer;

        Assert.isTrue(!Modifier.isAbstract(type.getModifiers()), "The type should to be a concrete class");

        enhancer = new Enhancer();
        enhancer.setSuperclass(type);
        enhancer.setClassLoader(type.getClassLoader());
        enhancer.setCallback(handler);
        return (T) enhancer.create();
    }

    /**
     * Create a proxy for the indicated type.
     * @param handler The handler
     * @param type The type, should to be a interface type
     * @return The proxy
     */
    @SuppressWarnings("unchecked")
    private <T> T newProxyForInterface(java.lang.reflect.InvocationHandler handler, Class<T> type) {
        Assert.isTrue(type.isInterface(), "The type should to be an interface");
        return (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, handler);
    }

    /**
     * A class for wrap a {@link IProxyHandler} into a "dynamic proxy" or a "cglib proxy".
     * @author Octavi Forns ofornes@albirar.cat
     * @since 2.1.0
     */
    class ProxyInvocationHandlerWrapper implements org.springframework.cglib.proxy.InvocationHandler,
            java.lang.reflect.InvocationHandler, org.springframework.cglib.proxy.Callback {
        private IProxyHandler proxyHandler;

        /**
         * Unique constructor.
         * @param proxyHandler The proxy handler to manage methods call
         */
        ProxyInvocationHandlerWrapper(IProxyHandler proxyHandler) {
            Assert.notNull(proxyHandler, "The proxy handler is required");
            this.proxyHandler = proxyHandler;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return proxyHandler.invokeMethod(proxy, method, args);
        }
    }
}