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

ro.isdc.wro.util.ProxyFactory Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
package ro.isdc.wro.util;

import static org.apache.commons.lang3.Validate.notNull;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashSet;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * An {@link ObjectFactory} used to create Proxy for objects initialized by provided {@link LazyInitializer}'s.
 *
 * @author Alex Objelean
 * @since 1.6.0
 * @created 14 Oct 2012
 * @param 
 *          the type of the object to create.
 */
public class ProxyFactory {
  private static final Logger LOG = LoggerFactory.getLogger(ProxyFactory.class);
  private final Class genericType;

  private final TypedObjectFactory objectFactory;

  /**
   * A specialized version of {@link ObjectFactory} which provides more information about type class. This is required
   * to avoid premature creation because the class cannot be extracted from generic type.
   */
  public static interface TypedObjectFactory  extends ObjectFactory {
    Class getObjectClass();
  }

  /**
   * Creates a proxy for the provided object.
   *
   * @param objectFactory
   *          Object factory for which a proxy will be created.
   * @param genericType
   *          the Class of the generic object, required to create the proxy. This argument is required because of type
   *          erasure and generics info aren't available at runtime.
   */
  private ProxyFactory(final TypedObjectFactory objectFactory, final Class genericType) {
    notNull(objectFactory);
    notNull(genericType);
    this.objectFactory = objectFactory;
    this.genericType = genericType;
  }

  public static  T proxy(final TypedObjectFactory objectFactory, final Class genericType) {
    try {
      return new ProxyFactory(objectFactory, genericType).create();
    } catch (final RuntimeException e) {
      LOG.error("exception", e);
      throw e;
    }
  }

  @SuppressWarnings("unchecked")
  private T create() {
    final InvocationHandler handler = new InvocationHandler() {
      @Override
      public Object invoke(final Object proxy, final Method method, final Object[] args)
          throws Throwable {
        try {
          return method.invoke(objectFactory.create(), args);
        } catch (final InvocationTargetException ex) {
          // Preserve original exception
          throw ex.getCause();
        }
      }
    };
    LOG.debug("genericType: {}", genericType);
    return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), getInterfacesSet().toArray(
        new Class[] {}), handler);
  }

  /**
   * @return a set of interfaces supported by proxied object.
   */
  private Set> getInterfacesSet() {
    final Set> set = new HashSet>();
    if (genericType.isInterface()) {
      set.add(genericType);
    }
    final Class[] classes = objectFactory.getObjectClass().getInterfaces();
    for (final Class clazz : classes) {
      set.add(clazz);
    }
    LOG.debug("interfaces set: {}", set);
    return set;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy