Package hermes.util

Source Code of hermes.util.ReflectUtils

/*
* Copyright 2003,2004,2005 Colin Crist
*
* 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 hermes.util;

import hermes.SystemProperties;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Set;
import java.util.StringTokenizer;

import javax.jms.ConnectionFactory;
import javax.jms.QueueConnectionFactory;
import javax.jms.TopicConnectionFactory;

import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.NoOp;

import org.apache.log4j.Logger;

/**
* Some useful reflection utilities.
*
* @author colincrist@hermesjms.com
* @version $Id: ReflectUtils.java,v 1.3 2006/07/26 09:47:56 colincrist Exp $
*/

public class ReflectUtils {
  private static final Set<String> nonCompliantPackages = new HashSet<String>();

  static {
    String prefixes = System.getProperty(SystemProperties.NON_COMPLIANT_PACKAGES, SystemProperties.DEFAULT_NON_COMPLIANT_PACKAGES);

    for (StringTokenizer tokens = new StringTokenizer(prefixes, ","); tokens.hasMoreTokens();) {
      nonCompliantPackages.add(tokens.nextToken());
    }
  }

  private static final Logger log = Logger.getLogger(ReflectUtils.class);

  /**
   * Is this method public and not static?
   *
   * @param m
   * @return
   */
  private static boolean isPublicAndNonStatic(Method m) {
    return !Modifier.isStatic(m.getModifiers()) && Modifier.isPublic(m.getModifiers());
  }

  /**
   * Is this method a getter? It is not 100% generic as I assume an array
   * paramter discounts it as being a setter.
   *
   * @param m
   * @return
   */
  public static boolean isGetter(Method m) {
    return m.getName().startsWith("get") && isPublicAndNonStatic(m) && m.getParameterTypes().length == 0;
  }

  /**
   * Is this method a getter? It is not 100% generic as I assume an array
   * paramter discounts it as being a getter.
   *
   * @param m
   * @return
   */
  public static boolean isSetter(Method m) {
    return m.getName().startsWith("set") && isPublicAndNonStatic(m) && m.getParameterTypes().length == 1 && !m.getParameterTypes()[0].isArray();
  }

  /**
   * Return the property type for a setter or setter (i.e. the return type or
   * argument)
   *
   * @param m
   * @return
   */
  public static Class getPropertyType(Method m) {
    if (isSetter(m)) {
      return m.getParameterTypes()[0];
    } else if (isGetter(m)) {
      return m.getReturnType();
    } else {
      return Void.class;
    }
  }

  /**
   * Return the property name for a getter or setter.
   *
   * @param m
   * @return
   */
  public static String getPropertyName(Method m) {
    String s = m.getName().substring(3, m.getName().length());

    return Character.toLowerCase(s.charAt(0)) + s.substring(1);
  }

  public static boolean getterExists(Class clazz, String propertyName) {
    final String methodName = "get" + propertyName;

    try {
      final Method method = clazz.getMethod(methodName, new Class[] {});

      return true;
    } catch (NoSuchMethodException e) {
      return false;
    }
  }

  /**
   * This is complicated, we code generate a new class to mix-in the methods
   * missing get methods from a bean and then intercept the getters and
   * setters, caching the succesful set call and returning it from the get
   * call.
   *
   * @param clazz
   * @return
   * @throws InstantiationException
   * @throws IllegalAccessException
   */
  public static Object mixinGetterMethodsAndInstantiate(Class clazz) throws InstantiationException, IllegalAccessException {
    //
    // Generate a bean class that has a full set of get/set methods for all
    // properties. The getters will
    // in fact never get called as the intercepter will return the cached
    // result of the previous setter.

    final Method[] methods = clazz.getMethods();
    final BeanGenerator beanGenerator = new BeanGenerator();

    beanGenerator.setSuperclass(clazz);

    for (int i = 0; i < methods.length; i++) {
      final Method m = methods[i];

      if (ReflectUtils.isSetter(m)) {
        beanGenerator.addProperty(ReflectUtils.getPropertyName(m), ReflectUtils.getPropertyType(m));
      }
    }

    //
    // Enhance the class by placing a GetCachingMethodInterceptor
    // intercepter on all the getter and setter methods.

    final Class newClazz = (Class) beanGenerator.createClass();

    final Callback[] callbacks = new Callback[] { new GetCachingMethodInterceptor(clazz.newInstance()), NoOp.INSTANCE };

    return (ConnectionFactory) Enhancer.create(newClazz, new Class[] { ConnectionFactory.class, QueueConnectionFactory.class, TopicConnectionFactory.class }, new CallbackFilter() {
      public int accept(Method m) {
        return 0 ;
      }

    }, callbacks);

  }

  public static ConnectionFactory createConnectionFactory(Class clazz) throws InstantiationException, IllegalAccessException {
    final ConnectionFactory factory = (ConnectionFactory) clazz.newInstance();

    if (nonCompliantPackages.contains(clazz.getPackage().getName())) {
      log.debug("found a non Java Bean compliant class, " + clazz.getName() + ", generating a new class and implementing an around advice to mixin getters");

      // return factory ;

      return (ConnectionFactory) mixinGetterMethodsAndInstantiate(clazz);
    } else {
      return factory;
    }
  }
}
TOP

Related Classes of hermes.util.ReflectUtils

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.