Package org.activiti.engine.impl.util

Source Code of org.activiti.engine.impl.util.ReflectUtil

/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.activiti.engine.impl.util;

import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.Arrays;
import java.util.logging.Logger;

import org.activiti.engine.ActivitiClassLoadingException;
import org.activiti.engine.ActivitiException;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.context.Context;


/**
* @author Tom Baeyens
*/
public abstract class ReflectUtil {

  private static final Logger LOG = Logger.getLogger(ReflectUtil.class.getName());
 
  public static ClassLoader getClassLoader() {
    ClassLoader loader = getCustomClassLoader();
    if(loader == null) {
      loader = Thread.currentThread().getContextClassLoader();
    }
    return loader;
  }
 
  public static Class<?> loadClass(String className) {
   Class<?> clazz = null;
   ClassLoader classLoader = getCustomClassLoader();
  
   // First exception in chain of classloaders will be used as cause when no class is found in any of them
   Throwable throwable = null;
  
   if(classLoader != null) {
     try {
       LOG.finest("Trying to load class with custom classloader: " + className);
       clazz = Class.forName(className, true, classLoader);
     } catch(Throwable t) {
       throwable = t;
     }
   }
   if(clazz == null) {
     try {
       LOG.finest("Trying to load class with current thread context classloader: " + className);
       clazz = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
     } catch(Throwable t) {
       if(throwable == null) {
         throwable = t;
       }
     }
     if(clazz == null) {
       try {
         LOG.finest("Trying to load class with local classloader: " + className);
         clazz = Class.forName(className, true, ReflectUtil.class.getClassLoader());
       } catch(Throwable t) {
         if(throwable == null) {
           throwable = t;
         }
       }
     }
   }
 
   if(clazz == null) {
     throw new ActivitiClassLoadingException(className, throwable);
   }
   return clazz;
  }
 
  public static InputStream getResourceAsStream(String name) {
    InputStream resourceStream = null;
    ClassLoader classLoader = getCustomClassLoader();
    if(classLoader != null) {
      resourceStream = classLoader.getResourceAsStream(name);
    }
   
    if(resourceStream == null) {
      // Try the current Thread context classloader
      classLoader = Thread.currentThread().getContextClassLoader();
      resourceStream = classLoader.getResourceAsStream(name);
      if(resourceStream == null) {
        // Finally, try the classloader for this class
        classLoader = ReflectUtil.class.getClassLoader();
        resourceStream = classLoader.getResourceAsStream(name);
      }
    }
    return resourceStream;
   }
 
  public static URL getResource(String name) {
    URL url = null;
    ClassLoader classLoader = getCustomClassLoader();
    if(classLoader != null) {
      url = classLoader.getResource(name);
    }
    if(url == null) {
      // Try the current Thread context classloader
      classLoader = Thread.currentThread().getContextClassLoader();
      url = classLoader.getResource(name);
      if(url == null) {
        // Finally, try the classloader for this class
        classLoader = ReflectUtil.class.getClassLoader();
        url = classLoader.getResource(name);
      }
    }
  
    return url;
   }

  public static Object instantiate(String className) {
    try {
      Class< ? > clazz = loadClass(className);
      return clazz.newInstance();
    } catch (Exception e) {
      throw new ActivitiException("couldn't instantiate class "+className, e);
    }
  }

  public static Object invoke(Object target, String methodName, Object[] args) {
    try {
      Class<? extends Object> clazz = target.getClass();
      Method method = findMethod(clazz, methodName, args);
      method.setAccessible(true);
      return method.invoke(target, args);
    } catch (Exception e) {
      throw new ActivitiException("couldn't invoke "+methodName+" on "+target, e);
    }
  }
 
  /**
   * Returns the field of the given object or null if it doesnt exist.
   */
  public static Field getField(String fieldName, Object object) {
    return getField(fieldName, object.getClass());
  }
 
  /**
   * Returns the field of the given class or null if it doesnt exist.
   */
  public static Field getField(String fieldName, Class<?> clazz) {
    Field field = null;
    try {
      field = clazz.getDeclaredField(fieldName);
    } catch (SecurityException e) {
      throw new ActivitiException("not allowed to access field " + field + " on class " + clazz.getCanonicalName());
    } catch (NoSuchFieldException e) {
      // for some reason getDeclaredFields doesnt search superclasses
      // (which getFields() does ... but that gives only public fields)
      Class<?> superClass = clazz.getSuperclass();
      if (superClass != null) {
        return getField(fieldName, superClass);
      }
    }
    return field;
  }
 
  public static void setField(Field field, Object object, Object value) {
    try {
      field.setAccessible(true);
      field.set(object, value);
    } catch (IllegalArgumentException e) {
      throw new ActivitiException("Could not set field " + field.toString(), e);
    } catch (IllegalAccessException e) {
      throw new ActivitiException("Could not set field " + field.toString(), e);
    }
  }
 
  /**
   * Returns the setter-method for the given field name or null if no setter exists.
   */
  public static Method getSetter(String fieldName, Class<?> clazz, Class<?> fieldType) {
    String setterName = "set" + Character.toTitleCase(fieldName.charAt(0)) +
      fieldName.substring(1, fieldName.length());
    try {
      // Using getMathods(), getMathod(...) expects exact parameter type
      // matching and ignores inheritance-tree.
      Method[] methods = clazz.getMethods();
      for(Method method : methods) {
        if(method.getName().equals(setterName)) {
          Class<?>[] paramTypes = method.getParameterTypes();
          if(paramTypes != null && paramTypes.length == 1 && paramTypes[0].isAssignableFrom(fieldType)) {
            return method;
          }
        }
      }
      return null;
    } catch (SecurityException e) {
      throw new ActivitiException("Not allowed to access method " + setterName + " on class " + clazz.getCanonicalName());
    }
  }

  private static Method findMethod(Class< ? extends Object> clazz, String methodName, Object[] args) {
    for (Method method : clazz.getDeclaredMethods()) {
      // TODO add parameter matching
      if ( method.getName().equals(methodName)
           && matches(method.getParameterTypes(), args)
         ) {
        return method;
      }
    }
    Class< ? > superClass = clazz.getSuperclass();
    if (superClass!=null) {
      return findMethod(superClass, methodName, args);
    }
    return null;
  }

  public static Object instantiate(String className, Object[] args) {
    Class< ? > clazz = loadClass(className);
    Constructor< ? > constructor = findMatchingConstructor(clazz, args);
    if (constructor==null) {
      throw new ActivitiException("couldn't find constructor for "+className+" with args "+Arrays.asList(args));
    }
    try {
      return constructor.newInstance(args);
    } catch (Exception e) {
      throw new ActivitiException("couldn't find constructor for "+className+" with args "+Arrays.asList(args), e);
    }
  }

  @SuppressWarnings({ "unchecked", "rawtypes" })
  private static <T> Constructor<T> findMatchingConstructor(Class<T> clazz, Object[] args) {
    for (Constructor constructor: clazz.getDeclaredConstructors()) { // cannot use <?> or <T> due to JDK 5/6 incompatibility
      if (matches(constructor.getParameterTypes(), args)) {
        return constructor;
      }
    }
    return null;
  }

  private static boolean matches(Class< ? >[] parameterTypes, Object[] args) {
    if ( (parameterTypes==null)
         || (parameterTypes.length==0)
       ) {
      return ( (args==null)
               || (args.length==0)
             );
    }
    if ( (args==null)
         || (parameterTypes.length!=args.length)
       ) {
      return false;
    }
    for (int i=0; i<parameterTypes.length; i++) {
      if ( (args[i]!=null)
           && (! parameterTypes[i].isAssignableFrom(args[i].getClass()))
         ) {
        return false;
      }
    }
    return true;
  }
 
  private static ClassLoader getCustomClassLoader() {
    ProcessEngineConfigurationImpl processEngineConfiguration = Context.getProcessEngineConfiguration();
    if(processEngineConfiguration != null) {
      final ClassLoader classLoader = processEngineConfiguration.getClassLoader();
      if(classLoader != null) {
        return classLoader;
      }
    }
    return null;
  }
}
TOP

Related Classes of org.activiti.engine.impl.util.ReflectUtil

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.