All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jingle.util.dydelegation.DelegationGenerator Maven / Gradle / Ivy

package org.jingle.util.dydelegation;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Delegation generator
 * 
 * @author JianLu
 * @version 1.0 2004-9-23
 * @since 1.0
 */
public class DelegationGenerator {
    /**
     * The generated delegation classes map. Key is DelegationGenerator.Key
     * instance, Value is generated class.
     */
    static Map classes = new HashMap();

    /**
     * Delegation Creator Factory instance
     */
    static DelegationCreatorFactory factory = new DelegationCreatorFactory();

    /**
     * 
     * The internal class represents the key of the generated classes map
     * 
     * @author JianLu
     * @version 1.0 2004-10-29
     * @since 1.0
     */
    static class Key {
        /**
         * Source class names
         */
        Set srcClassNames = new HashSet();

        /**
         * Target class name
         */
        String targetClassName;

        /**
         * Constructor
         * 
         * @param srcClassName
         *            Source class name
         * @param targetClassName
         *            Target class name
         */
        public Key(Class[] srcClasses, String targetClassName) {
            if (srcClasses != null) {
                for (int i = 1; i <= srcClasses.length; i++) {
                    srcClassNames.add(srcClasses[i - 1].getName());
                }
            }
            this.targetClassName = targetClassName;
        }

        /**
         * (non-Javadoc)
         * 
         * @see java.lang.Object#equals(java.lang.Object)
         */
        public boolean equals(Object obj) {
            if (obj instanceof Key) {
                Key key = (Key) obj;
                if (srcClassNames.equals(key.srcClassNames)
                        && ((targetClassName == null) ? (key.targetClassName == null)
                                : targetClassName.equals(key.targetClassName)))
                    return true;
            }
            return false;
        }

        /**
         * (non-Javadoc)
         * 
         * @see java.lang.Object#hashCode()
         */
        public int hashCode() {
            return srcClassNames.hashCode() + ("" + targetClassName).hashCode();
        }
    }

    /**
     * Protected constructor to avoid user to instantiate it
     *
     */
    protected DelegationGenerator() {
    }

    /**
     * Get the DelegationInvocationHandler of a specific delegation object
     * 
     * @param delegation
     *            The delegation object
     * @return DelegationInvocationHandler of the delegation object. If the
     *         object is not a delegation, return null.
     */
    public static DelegationInvocationHandler getInvocationHandler(
            Object delegation) {
        if (isDelegation(delegation)) {
            return ((Delegation) delegation)._getInvocationHandler();
        }
        return null;
    }

    /**
     * Set the delegation creator factory
     * 
     * @param factory
     *            DelegationCreatorFactory
     */
    public static void setDelegationCreatorFactory(
            DelegationCreatorFactory factory) {
        DelegationGenerator.factory = factory;
    }

    /**
     * It is same as getDelegationClass(null, beanClasses).
     * 
     * @see org.jingle.util.dydelegation.DelegationGenerator#getDelegationClass(java.lang.String,
     *      java.lang.Class[])
     * @param beanClasses
     *            The classes to be delegated.
     * @return The delegation class
     */
    public static synchronized Class getDelegationClass(Class[] beanClasses) {
        return getDelegationClass(null, beanClasses);
    }

    /**
     * Get delegation class for a specific class
     * 
     * @param targetClassName
     *            The generated delegation class full name. If it is null, the
     *            generator will give a system generated class name. The default
     *            package is same as the source class package.
     * @param beanClasses
     *            The classes to be delegated. The class array can contains 1 class
     *            at most and can contains multiple interfaces.
     * @return The delegation class
     */
    public static synchronized Class getDelegationClass(String targetClassName,
            Class[] beanClasses) {
        Key key = new Key(beanClasses, targetClassName);
        Class ret = (Class) classes.get(key);
        if (ret == null) {
            DelegationCreator creator = factory.getCreator(targetClassName,
                    beanClasses);
            FileOutputStream os = null;
//                      try {
//                          os = new FileOutputStream(
//                          "c:/temp/TestBean_Delegation_0.class");
//                      } catch (FileNotFoundException e) {
//                          // TODO Auto-generated catch block
//                          e.printStackTrace();
//                      }
            try {
                ret = creator.create(os);
            } catch (IOException e1) {
                e1.printStackTrace();
            } finally {
                if (os != null) {
                    try {
                        os.close();
                    } catch(Exception e) {
                    }
                }
            }
            if (ret != null) {
                classes.put(key, ret);
            }
        }
        return ret;
    }

    /**
     * Check whether the class is a delegation class or not
     * 
     * @param beanClass
     *            The class to be checked
     * @return true if the input class is a delegation class.
     */
    public static boolean isDelegationClass(Class beanClass) {
        if (Delegation.class.isAssignableFrom(beanClass))
            return true;
        return false;
    }

    /**
     * Check whether the object is a delegation object or not
     * 
     * @param obj
     *            The object to be checked
     * @return true if the input object is a delegation object
     */
    public static boolean isDelegation(Object obj) {
        return isDelegationClass(obj.getClass());
    }

    /**
     * It is same as newDelegationInstance(bean, null, h)
     * 
     * @see org.jingle.util.dydelegation.DelegationGenerator#newDelegationInstance(java.lang.Object,
     *      java.lang.String,
     *      org.jingle.util.dydelegation.DelegationInvocationHandler)
     * @param bean
     *            The object to be delegated
     * @param h
     *            The delegation invocation handler
     * @return The generated delegation object
     */
    public static Object newDelegationInstance(Object bean,
            DelegationInvocationHandler h) {
        return newDelegationInstance(bean, null, h);
    }

    /**
     * It is same as newDelegationInstance(bean, null, paraTypes, paras, h)
     * 
     * @see org.jingle.util.dydelegation.DelegationGenerator#newDelegationInstance(java.lang.Object,
     *      java.lang.String, java.lang.Class[], java.lang.Object[],
     *      org.jingle.util.dydelegation.DelegationInvocationHandler)
     * @param bean
     *            The object to be delegated
     * @param paraTypes The parameter types for the constructor of delegated class
     * @param paras The parameter values for the constructor of delegated class
     * @param h
     *            The delegation invocation handler
     * @return The generated delegation object
     */
    public static Object newDelegationInstance(Object bean, Class[] paraTypes, Object[] paras,
            DelegationInvocationHandler h) {
        return newDelegationInstance(bean, null, paraTypes, paras, h);
    }

    /**
     * It is same as newDelegationInstance(bean, new Class[] {bean.getClass()},
     * targetClassName, h)
     * 
     * @see org.jingle.util.dydelegation.DelegationGenerator#newDelegationInstance(java.lang.Object,
     *      java.lang.Class[], java.lang.String,
     *      org.jingle.util.dydelegation.DelegationInvocationHandler)
     * @param bean
     *            The object to be delegated
     * @param targetClassName
     *            The generated delegation's class name. If null, a system generated name is provided.
     * @param h
     *            The delegation invocation handler
     * @return The generated delegation object
     */
    public static Object newDelegationInstance(Object bean,
            String targetClassName, DelegationInvocationHandler h) {
        return newDelegationInstance(bean, new Class[] { bean.getClass() },
                targetClassName, h);
    }

    /**
     * It is same as newDelegationInstance(bean, new Class[] {bean.getClass()},
     * targetClassName, paraTypes, paras, h)
     * 
     * @see org.jingle.util.dydelegation.DelegationGenerator#newDelegationInstance(java.lang.Object,
     *      java.lang.Class[], java.lang.String, java.lang.Class[], java.lang.Object[],
     *      org.jingle.util.dydelegation.DelegationInvocationHandler)
     * @param bean
     *            The object to be delegated
     * @param targetClassName
     *            The generated delegation's class name. If null, a system generated name is provided.
     * @param paraTypes The parameter types for the constructor of delegated class
     * @param paras The parameter values for the constructor of delegated class
     * @param h
     *            The delegation invocation handler
     * @return The generated delegation object
     */
    public static Object newDelegationInstance(Object bean,
            String targetClassName, Class[] paraTypes, Object[] paras,
            DelegationInvocationHandler h) {
        return newDelegationInstance(bean, new Class[] { bean.getClass() },
                targetClassName, paraTypes, paras, h);
    }

    /**
     * It is same as newDelegationInstance(bean, beanClasses, 
     * new Class[0], new Object[0], targetClassName, h)
     *
     * @see org.jingle.util.dydelegation.DelegationGenerator#newDelegationInstance(java.lang.Object,
     *      java.lang.Class[], java.lang.String, java.lang.Class[], java.lang.Object[],
     *      org.jingle.util.dydelegation.DelegationInvocationHandler)
     * 
     * @param bean
     *            The object to be delegated
     * @param beanClasses
     *            The classes to be delegated. If bean is not null, it should
     *            an instance of these classes. The calss array can contains 1
     *            class at most and can contains multiple interfaces.
     * @param targetClassName
     *            The generated delegation's class name, it is useful when want
     *            to delegate a java core class. If null, a system generated name is provided.
     * @param h
     *            The delegation invocation handler
     * @return The generated delegation object
     */
    public static Object newDelegationInstance(Object bean,
            Class[] beanClasses, String targetClassName,
            DelegationInvocationHandler h) {
        return newDelegationInstance(bean, beanClasses,
                targetClassName, new Class[0], new Object[0], h);
    }

    /**
     * Create a delegation instance for the specific object
     * 
     * @param bean
     *            The object to be delegated
     * @param beanClasses
     *            The classes to be delegated. If bean is not null, it should
     *            an instance of these classes. The calss array can contains 1
     *            class at most and can contains multiple interfaces.
     * @param targetClassName
     *            The generated delegation's class name, it is useful when want
     *            to delegate a java core class. If null, a system generated name is provided.
     * @param paraTypes The parameter types for the constructor of delegated class
     * @param paras The parameter values for the constructor of delegated class
     * @param h
     *            The delegation invocation handler
     * @return The generated delegation object
     */
    public static Object newDelegationInstance(Object bean,
            Class[] beanClasses, String targetClassName,
            Class[] paraTypes, Object[] paras,
            DelegationInvocationHandler h) {
        Object ret = null;
//        if (bean != null) {
//            if (beanClasses != null) {
//                Class clazz = bean.getClass();
//                for (int i = 1; i <= beanClasses.length; i++) {
//                    if (!beanClasses[i - 1].isAssignableFrom(clazz))
//                        throw new IllegalArgumentException("The bean object must be an instance of each beanClass");
//                }
//            }
//        }
        Class clazz = getDelegationClass(targetClassName, beanClasses);
        try {
            Class[] constructorParaTypes = new Class[paraTypes.length + 1];
            Object[] constructorParas = new Object[paras.length + 1];
            constructorParaTypes[0] = Object.class;
            constructorParas[0] = bean;
            System.arraycopy(paraTypes, 0, constructorParaTypes, 1, paraTypes.length);
            System.arraycopy(paras, 0, constructorParas, 1, paras.length);
            Constructor c = clazz.getConstructor(constructorParaTypes);
            ret = c.newInstance(constructorParas);
            ((Delegation) ret)._setInvocationHandler(h);
        } catch (IllegalArgumentException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException(e.toString());
        }
        return ret;
    }
}





© 2015 - 2025 Weber Informatics LLC | Privacy Policy