Package railo.runtime.reflection

Source Code of railo.runtime.reflection.Invoker

package railo.runtime.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import railo.commons.lang.StringUtil;
import railo.runtime.exp.PageException;
import railo.runtime.op.Caster;
import railo.runtime.reflection.pairs.ConstructorParameterPair;
import railo.runtime.reflection.pairs.MethodParameterPair;
import railo.runtime.type.ObjectWrap;

/**
* To invoke a Object on different ways
*/
public final class Invoker {

    private static Method[] lastMethods;
    private static Class lastClass;


  /**
   * @param clazz
   * @param parameters
   * @return new Instance
   * @throws NoSuchMethodException
   * @throws IllegalArgumentException
   * @throws InstantiationException
   * @throws IllegalAccessException
   * @throws InvocationTargetException
   */
  public static Object newInstance(Class clazz, Object[] parameters) throws NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException  {
    ConstructorParameterPair pair=
      getConstructorParameterPairIgnoreCase(clazz, parameters);
    return pair.getConstructor().newInstance(pair.getParameters());
  }
 

  /**
   * search the matching constructor to defined parameter list, also translate parameters for matching
   * @param clazz class to get constructo from
   * @param parameters parameter for the constructor
   * @return  Constructor parameter pair
   * @throws NoSuchMethodException
   */
  public static ConstructorParameterPair getConstructorParameterPairIgnoreCase(Class clazz, Object[] parameters) throws NoSuchMethodException {
    // set all values
    //Class objectClass=object.getClass();
    if(parameters==null)parameters=new Object[0];
 
  // set parameter classes
    Class[] parameterClasses=new Class[parameters.length];
    for(int i=0;i<parameters.length;i++) {
      parameterClasses[i]=parameters[i].getClass();
    }
 
  // search right method
    Constructor[] constructor=clazz.getConstructors();
    for(int mode=0;mode<2;mode++) {
      outer: for(int i=0;i<constructor.length;i++) {
        Constructor c=constructor[i];
       
       
        Class[] paramTrg=c.getParameterTypes();
        // Same Parameter count
        if(parameterClasses.length==paramTrg.length) {
          for(int y=0;y<parameterClasses.length;y++) {
            if(mode==0 && parameterClasses[y]!=primitiveToWrapperType(paramTrg[y])) {
              continue outer;
            }
            else if(mode==1) {
              Object o=compareClasses(parameters[y], paramTrg[y]);
              if(o==null)continue outer;
             
                parameters[y]=o;
                parameterClasses[y]=o.getClass();
             
            }
          }
        return new ConstructorParameterPair(c,parameters);
        }
       
      }
    }
   
    // Exeception
    String parameter="";
    for(int i=0;i<parameterClasses.length;i++) {
      if(i!=0) parameter+=", ";
      parameter+=parameterClasses[i].getName();
    }
    throw new NoSuchMethodException("class constructor "+clazz.getName()+"("+parameter+") doesn't exist");
  }
 
 
 
 
  /**
   * call of a method from given object
   * @param object object to call method from
   * @param methodName name of the method to call
   * @param parameters parameter for method
   * @return return value of the method
   * @throws SecurityException
   * @throws NoSuchMethodException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws InvocationTargetException
  */
  public static Object callMethod(Object object, String methodName, Object[] parameters) throws NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException  {
      MethodParameterPair pair=
      getMethodParameterPairIgnoreCase(object.getClass(), methodName, parameters);

       
    return pair.getMethod().invoke(object,pair.getParameters());
  }
 
  /**
   * search the matching method to defined Method Name, also translate parameters for matching
   * @param objectClass class object where searching method from
   * @param methodName name of the method to search
   * @param parameters whished parameter list
   * @return pair with method matching and parameterlist matching
   * @throws NoSuchMethodException
   */
  public static MethodParameterPair getMethodParameterPairIgnoreCase(Class objectClass, String methodName, Object[] parameters) throws NoSuchMethodException {
    // set all values
      if(parameters==null)parameters=new Object[0];
   
    // set parameter classes
      Class[] parameterClasses=new Class[parameters.length];
      for(int i=0;i<parameters.length;i++) {
        parameterClasses[i]=parameters[i].getClass();
      }
         
    // search right method
      Method[] methods=null;
     
      if(lastClass!=null && lastClass.equals(objectClass)) {
          methods=lastMethods;
      }
      else {
          methods=objectClass.getDeclaredMethods();
      }
     
      lastClass=objectClass;
      lastMethods=methods;
      //Method[] methods=objectClass.getMethods();
      //Method[] methods=objectClass.getDeclaredMethods();
     
      //methods=objectClass.getDeclaredMethods();
      for(int mode=0;mode<2;mode++) {
        outer: for(int i=0;i<methods.length;i++) {
          Method method=methods[i];
          // Same Name
          if(method.getName().equalsIgnoreCase(methodName)) {
            Class[] paramTrg=method.getParameterTypes();
            // Same Parameter count
            if(parameterClasses.length==paramTrg.length) {
              //if(parameterClasses.length==0)return m;
              for(int y=0;y<parameterClasses.length;y++) {
               
                if(mode==0 && parameterClasses[y]!=primitiveToWrapperType(paramTrg[y])) {
                  continue outer;
                }
                else if(mode==1) {
                  Object o=compareClasses(parameters[y], paramTrg[y]);
                 
                  if(o==null) {
                      continue outer;
                  }
                  parameters[y]=o;
                  parameterClasses[y]=o.getClass();
                 
                }
                //if(parameterClasses.length-1==y) return m;
              }
           
            return new MethodParameterPair(method,parameters);
            }
          }
        }
      }
     
      // Exeception
  String parameter="";
      for(int i=0;i<parameterClasses.length;i++) {
        if(i!=0) parameter+=", ";
        parameter+=parameterClasses[i].getName();
      }
      throw new NoSuchMethodException("method "+methodName+"("+parameter+") doesn't exist in class "+objectClass.getName());
   
  }
 
  /**
   * compare parameter with whished parameter class and convert parameter to whished type
   * @param parameter parameter to compare
   * @param trgClass whished type of the parameter
   * @return converted parameter (to whished type) or null
   */
  private static Object compareClasses(Object parameter, Class trgClass) {
    Class srcClass=parameter.getClass();
    trgClass=primitiveToWrapperType(trgClass);
    try {
      if(parameter instanceof ObjectWrap)
        parameter=((ObjectWrap)parameter).getEmbededObject();
   
    // parameter is already ok
   
      if(srcClass==trgClass) return parameter;
     
      else if (instaceOf(srcClass,trgClass)) {
        return parameter;
      }
      else if (trgClass.getName().equals("java.lang.String")) {
        return Caster.toString(parameter);
      }
      else if (trgClass.getName().equals("java.lang.Boolean")) {
        return Caster.toBoolean(parameter);
      }
      else if (trgClass.getName().equals("java.lang.Byte")) {
        return new Byte( Caster.toString(parameter));
      }
      else if (trgClass.getName().equals("java.lang.Character")) {
        String str = Caster.toString(parameter);
        if(str.length()==1) return new Character(str.toCharArray()[0]);
        return null;
      }
      else if (trgClass.getName().equals("java.lang.Short")) {
        return Short.valueOf((short) Caster.toIntValue(parameter));
      }
      else if (trgClass.getName().equals("java.lang.Integer")) {
        return Integer.valueOf(Caster.toIntValue(parameter));
      }
      else if (trgClass.getName().equals("java.lang.Long")) {
        return Long.valueOf((long)Caster.toDoubleValue(parameter));
      }
      else if (trgClass.getName().equals("java.lang.Float")) {
        return Float.valueOf((float)Caster.toDoubleValue(parameter));
      }
      else if (trgClass.getName().equals("java.lang.Double")) {
        return Caster.toDouble(parameter);
      }
    }
    catch (PageException e) {
      return null;
    }
   
    return null;
  }

  /**
   * @param srcClass
   * @param trgClass
   * @return is instance of or not
   */
  private static boolean instaceOf(Class srcClass, Class trgClass) {
    while(srcClass!=null) {
        if(srcClass==trgClass) return true;
      srcClass=primitiveToWrapperType(srcClass.getSuperclass());
    }
    return false;
  }


  /**
   * cast a primitive type class definition to his object reference type
   * @param clazz class object to check and convert if it is of primitive type
   * @return object reference class object
   */
  private static Class primitiveToWrapperType(Class clazz) {
    // boolean, byte, char, short, int, long, float, and double
    if(clazz==null) return null;
    else if(clazz.isPrimitive()) {
      if(clazz.getName().equals("boolean"))return Boolean.class;
      else if(clazz.getName().equals("byte"))return Byte.class;
      else if(clazz.getName().equals("char"))return Character.class;
      else if(clazz.getName().equals("short"))return Short.class;
      else if(clazz.getName().equals("int"))return Integer.class;
      else if(clazz.getName().equals("long"))return Long.class;
      else if(clazz.getName().equals("float"))return Float.class;
      else if(clazz.getName().equals("double"))return Double.class;
    }
    return clazz;
  }

  /**
   * to invoke a getter Method of a Object
   * @param o Object to invoke method from
   * @param prop Name of the Method without get
   * @return return Value of the getter Method
   * @throws SecurityException
   * @throws NoSuchMethodException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws InvocationTargetException
   */
  public static Object callGetter(Object o, String prop) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    prop="get"+prop;
    Class c=o.getClass();
    Method m=getMethodParameterPairIgnoreCase(c, prop, null).getMethod();

    //Method m=getMethodIgnoreCase(c,prop,null);
    if(m.getReturnType().getName().equals("void"))
      throw new NoSuchMethodException("invalid return Type, method ["+m.getName()+"] can't have return type void");
    return m.invoke(o,null);
  }
 
  /**
   * to invoke a setter Method of a Object
   * @param o Object to invoke method from
   * @param prop Name of the Method without get
   * @param value Value to set to the Method
   * @throws SecurityException
   * @throws NoSuchMethodException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws InvocationTargetException
   */
  public static void callSetter(Object o, String prop,Object value) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
    prop="set"+StringUtil.ucFirst(prop);
    Class c=o.getClass();
    //Class[] cArg=new Class[]{value.getClass()};
    Object[] oArg=new Object[]{value};
    MethodParameterPair mp = getMethodParameterPairIgnoreCase(c, prop, oArg);
    //Method m=getMethodIgnoreCase(c,prop,cArg);
    if(!mp.getMethod().getReturnType().getName().equals("void"))
      throw new NoSuchMethodException("invalid return Type, method ["+mp.getMethod().getName()+"] must have return type void, now ["+mp.getMethod().getReturnType().getName()+"]");
    mp.getMethod().invoke(o,mp.getParameters());
  }
 
  /**
   * to get a visible Property of a object
   * @param o Object to invoke
   * @param prop property to call
   * @return property value
   * @throws NoSuchFieldException
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   */
  public static Object getProperty(Object o, String prop) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
    Field f=getFieldIgnoreCase(o.getClass(),prop);
    return f.get(o);
  }
 
  /**
   * assign a value to a visible property of a object
   * @param o Object to assign value to his property
   * @param prop name of property
   * @param value Value to assign
   * @throws IllegalArgumentException
   * @throws IllegalAccessException
   * @throws NoSuchFieldException
   */
  public static void setProperty(Object o, String prop,Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException {
    getFieldIgnoreCase(o.getClass(),prop).set(o,value);
  }

  /**
   * same like method getField from Class but ignore case from field name
   * @param c class to search the field
   * @param name name to search
   * @return Matching Field
   * @throws NoSuchFieldException
   */
  public static Field getFieldIgnoreCase(Class c, String name) throws NoSuchFieldException  {
    Field[] fields=c.getFields();
    for(int i=0;i<fields.length;i++) {
      Field f=fields[i];
      // Same Name
      if(f.getName().equalsIgnoreCase(name)) {
        return f;
      }
    }
    throw new NoSuchFieldException("Field doesn't exist");
  }
 
  /**
   * call of a static method of a Class
   * @param staticClass class how contains method to invoke
   * @param methodName method name to invoke
   * @param values Arguments for the Method
   * @return return value from method
   * @throws PageException
  */
  public static Object callStaticMethod(Class staticClass, String methodName, Object[] values) throws PageException {
    if(values==null)values=new Object[0];
   
   
   
   
    MethodParameterPair mp;
    try {
      mp = getMethodParameterPairIgnoreCase(staticClass, methodName, values);
    }
    catch (NoSuchMethodException e) {
      throw Caster.toPageException(e);
    }
   
    try {
      return mp.getMethod().invoke(null,mp.getParameters());
    }
    catch (InvocationTargetException e) {
      Throwable target = e.getTargetException();
      if(target instanceof PageException) throw (PageException)target;
      throw Caster.toPageException(e.getTargetException());
    }
    catch (Exception e) {
      throw Caster.toPageException(e);
    }
  }
}
TOP

Related Classes of railo.runtime.reflection.Invoker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.