Open Source Repository

Home /hibernate/hibernate-3.2.6.ga | Repository Home



org/hibernate/bytecode/cglib/ProxyFactoryFactoryImpl.java
package org.hibernate.bytecode.cglib;

import org.hibernate.bytecode.ProxyFactoryFactory;
import org.hibernate.bytecode.BasicProxyFactory;
import org.hibernate.proxy.ProxyFactory;
import org.hibernate.proxy.pojo.cglib.CGLIBProxyFactory;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.CallbackFilter;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.NoOp;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;

import java.lang.reflect.Method;
import java.util.HashMap;

/**
 * A factory for CGLIB-based {@link ProxyFactory} instances.
 *
 @author Steve Ebersole
 */
public class ProxyFactoryFactoryImpl implements ProxyFactoryFactory {

  /**
   * Builds a CGLIB-based proxy factory.
   *
   @return a new CGLIB-based proxy factory.
   */
  public ProxyFactory buildProxyFactory() {
    return new CGLIBProxyFactory();
  }

  public BasicProxyFactory buildBasicProxyFactory(Class superClass, Class[] interfaces) {
    return new BasicProxyFactoryImplsuperClass, interfaces );
  }

  public static class BasicProxyFactoryImpl implements BasicProxyFactory {
    private final Class proxyClass;
    private final Factory factory;

    public BasicProxyFactoryImpl(Class superClass, Class[] interfaces) {
      if superClass == null && interfaces == null || interfaces.length < ) ) {
        throw new AssertionFailure"attempting to build proxy without any superclass or interfaces" );
      }

      Enhancer en = new Enhancer();
      en.setUseCachefalse );
      en.setInterceptDuringConstructionfalse );
      en.setUseFactorytrue );
      en.setCallbackTypesCALLBACK_TYPES );
      en.setCallbackFilterFINALIZE_FILTER );
      if superClass != null ) {
        en.setSuperclasssuperClass );
      }
      if interfaces != null && interfaces.length > ) {
        en.setInterfacesinterfaces );
      }
      proxyClass = en.createClass();
      try {
        factory = Factory proxyClass.newInstance();
      }
      catch Throwable t ) {
        throw new HibernateException"Unable to build CGLIB Factory instance" );
      }
    }

    public Object getProxy() {
      try {
        return factory.newInstance(
            new Callback[] { new PassThroughInterceptorproxyClass.getName() ), NoOp.INSTANCE }
        );
      }
      catch Throwable t ) {
        throw new HibernateException"Unable to instantiate proxy instance" );
      }
    }
  }

  private static final CallbackFilter FINALIZE_FILTER = new CallbackFilter() {
    public int accept(Method method) {
      if method.getParameterTypes().length == && method.getName().equals("finalize") ){
        return 1;
      }
      else {
        return 0;
      }
    }
  };

  private static final Class[] CALLBACK_TYPES = new Class[] { MethodInterceptor.class, NoOp.class };

  private static class PassThroughInterceptor implements MethodInterceptor {
    private HashMap data = new HashMap();
    private final String proxiedClassName;

    public PassThroughInterceptor(String proxiedClassName) {
      this.proxiedClassName = proxiedClassName;
    }

    public Object intercept(
        Object obj,
            Method method,
            Object[] args,
            MethodProxy proxythrows Throwable {
      String name = method.getName();
      if "toString".equalsname ) ) {
        return proxiedClassName + "@" + System.identityHashCodeobj );
      }
      else if "equals".equalsname ) ) {
        return args[0instanceof Factory && ( ( Factory args[0] ).getCallback== this
            ? Boolean.TRUE
                  : Boolean.FALSE;
      }
      else if "hashCode".equalsname ) ) {
        return new IntegerSystem.identityHashCodeobj ) );
      }
      boolean hasGetterSignature = method.getParameterTypes().length == && method.getReturnType() != null;
      boolean hasSetterSignature = method.getParameterTypes().length == && method.getReturnType() == null || method.getReturnType() == void.class );
      if name.startsWith"get" && hasGetterSignature ) {
        String propName = name.substring);
        return data.getpropName );
      }
      else if name.startsWith"is" && hasGetterSignature ) {
        String propName = name.substring);
        return data.getpropName );
      }
      else if name.startsWith"set" && hasSetterSignature) {
        String propName = name.substring);
        data.putpropName, args[0] );
        return null;
      }
      else {
        // todo : what else to do here?
        return null;
      }
    }
  }
}