org.openlegacy.utils.ProxyUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.openlegacy.utils.ProxyUtil.java

Source

/*******************************************************************************
 * Copyright (c) 2014 OpenLegacy Inc.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     OpenLegacy Inc. - initial API and implementation
 *******************************************************************************/
package org.openlegacy.utils;

import net.sf.cglib.proxy.Enhancer;

import org.aopalliance.intercept.Interceptor;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.aop.TargetClassAware;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.util.Assert;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;

public class ProxyUtil {

    public static <T> T getTargetObject(Object proxy) {
        return getTargetObject(proxy, false);
    }

    @SuppressWarnings("unchecked")
    public static <T> T getTargetObject(Object proxy, boolean deep) {

        if (proxy == null) {
            return null;
        }

        while (proxy instanceof Advised) {
            try {
                if (deep) {
                    // invoke all getters
                    PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(proxy);
                    for (PropertyDescriptor propertyDescriptor : properties) {
                        try {
                            Class<?> propertyType = propertyDescriptor.getPropertyType();
                            if (propertyType != null && !TypesUtil.isPrimitive(propertyType)) {
                                Method readMethod = propertyDescriptor.getReadMethod();
                                if (readMethod != null) {
                                    readMethod.invoke(proxy);
                                }
                            }
                        } catch (Exception e) {
                            throw (new RuntimeException(e));
                        }
                    }
                }
                proxy = ((Advised) proxy).getTargetSource().getTarget();
            } catch (Exception e) {
                throw (new IllegalStateException(e));
            }
        }

        if (deep) {
            DirectFieldAccessor fieldAccessor = new DirectFieldAccessor(proxy);
            PropertyDescriptor[] properties = PropertyUtils.getPropertyDescriptors(proxy);
            for (PropertyDescriptor propertyDescriptor : properties) {
                try {
                    Object value = propertyDescriptor.getReadMethod().invoke(proxy);
                    Object afterValue = getTargetObject(value, false);
                    if (value != afterValue) {
                        fieldAccessor.setPropertyValue(propertyDescriptor.getName(), afterValue);
                    }
                } catch (Exception e) {
                    throw (new RuntimeException(e));
                }
            }
        }
        return (T) proxy;
    }

    @SuppressWarnings("unchecked")
    public static <T> T getTargetJpaObject(Object proxy, boolean children) {
        try {
            Map<Object, Object> processed = new HashMap<Object, Object>();
            Dehibernator dehibernator = new Dehibernator();
            proxy = getTargetJpaObject(proxy, children, dehibernator, processed);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return (T) proxy;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private static <T> T getTargetJpaObject(Object proxy, boolean children, Dehibernator dehibernator,
            Map<Object, Object> processed)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        if (proxy == null || processed.containsKey(proxy.getClass().getSimpleName())) {
            return null;
        }

        if (proxy instanceof Collection) {
            for (Object object : (Collection) proxy) {
                object = fetchLazyObject(object, dehibernator, children, processed);
            }
        } else if (proxy instanceof Map) {
            Collection collection = ((Map) proxy).values();
            for (Object object : collection) {
                object = fetchLazyObject(object, dehibernator, children, processed);
            }
        } else {
            proxy = fetchLazyObject(proxy, dehibernator, children, processed);
        }

        return (T) proxy;
    }

    @SuppressWarnings("unchecked")
    private static <T> T fetchLazyObject(Object proxy, Dehibernator dehibernator, boolean children,
            Map<Object, Object> processed)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        Field[] declaredFields = proxy.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            Class<?> type = field.getType();

            Entity entityAnnotation = type.getAnnotation(Entity.class);

            if (processed.containsKey(type.getSimpleName())) {
                setFieldValue(field, proxy, null);
            } else if (type.isAssignableFrom(List.class)) {
                processField(field, proxy, dehibernator, children, processed);
            } else if (type.isAssignableFrom(Map.class)) {
                processField(field, proxy, dehibernator, children, processed);
            } else if (entityAnnotation != null) {
                processField(field, proxy, dehibernator, children, processed);
            }

        }
        return (T) proxy;
    }

    private static void processField(Field field, Object proxy, Dehibernator dehibernator, boolean children,
            Map<Object, Object> processed)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        OneToMany otmAnnotation = field.getAnnotation(OneToMany.class);
        ManyToOne mtoAnnotation = field.getAnnotation(ManyToOne.class);

        if (otmAnnotation != null || mtoAnnotation != null) {
            if (children || (otmAnnotation != null && otmAnnotation.fetch().equals(FetchType.EAGER))
                    || (mtoAnnotation != null && mtoAnnotation.fetch().equals(FetchType.EAGER))) {
                for (Method method : proxy.getClass().getMethods()) {
                    if (method.getName().equals("get" + StringUtils.capitalize(field.getName()))) {
                        Object res = method.invoke(proxy, new Object[0]);
                        if (res != null) {
                            res.toString();
                            res = dehibernator.clean(res);
                            processed.put(proxy.getClass().getSimpleName(), proxy);
                            setFieldValue(field, proxy, res);
                            getTargetJpaObject(res, children, dehibernator, processed);
                        }
                    }
                }
            } else {
                setFieldValue(field, proxy, null);
            }
        }
    }

    private static void setFieldValue(Field field, Object proxy, Object value)
            throws IllegalAccessException, IllegalArgumentException {
        field.setAccessible(true);
        field.set(proxy, value);

    }

    public static Class<?> getObjectRealClass(Object object) {
        while (object instanceof TargetClassAware) {
            object = ((TargetClassAware) object).getTargetClass();
        }
        return object.getClass();
    }

    public static Class<?> getOriginalClass(Class<?> entityClass) {
        while (Enhancer.isEnhanced(entityClass)) {
            entityClass = entityClass.getSuperclass();
        }
        return entityClass;
    }

    public static boolean isClassesMatch(Class<?> classA, Class<?> classB) {
        return isClassesMatch(classA, classB, false);
    }

    public static boolean isClassesMatch(Class<?> classA, Class<?> classB, boolean allowNulls) {
        if (allowNulls) {
            if (classA == null || classB == null) {
                return false;
            }
        } else {
            Assert.notNull(classA);
            Assert.notNull(classB);
        }

        classA = getOriginalClass(classA);
        classB = getOriginalClass(classB);

        return (classA == classB);
    }

    public static Object createPojoProxy(Class<?> entityClass, Class<?> entityInterface, Interceptor interceptor) {
        Object entity = ReflectionUtil.newInstance(entityClass);
        ProxyFactory proxyFactory = new ProxyFactory(entityInterface, interceptor);

        proxyFactory.setTarget(entity);
        proxyFactory.setProxyTargetClass(true);
        Object entityProxy = proxyFactory.getProxy();

        return entityProxy;
    }
}